# Java中多線程和線程安全是什么
## 目錄
1. [多線程基礎概念](#一多線程基礎概念)
- 1.1 [什么是線程](#11-什么是線程)
- 1.2 [線程與進程的區別](#12-線程與進程的區別)
- 1.3 [為什么需要多線程](#13-為什么需要多線程)
2. [Java中的線程實現](#二java中的線程實現)
- 2.1 [繼承Thread類](#21-繼承thread類)
- 2.2 [實現Runnable接口](#22-實現runnable接口)
- 2.3 [實現Callable接口](#23-實現callable接口)
- 2.4 [三種方式對比](#24-三種方式對比)
3. [線程生命周期](#三線程生命周期)
- 3.1 [線程狀態圖解](#31-線程狀態圖解)
- 3.2 [狀態轉換詳解](#32-狀態轉換詳解)
4. [線程安全核心問題](#四線程安全核心問題)
- 4.1 [原子性問題](#41-原子性問題)
- 4.2 [可見性問題](#42-可見性問題)
- 4.3 [有序性問題](#43-有序性問題)
5. [線程安全解決方案](#五線程安全解決方案)
- 5.1 [synchronized關鍵字](#51-synchronized關鍵字)
- 5.2 [Lock接口](#52-lock接口)
- 5.3 [volatile關鍵字](#53-volatile關鍵字)
- 5.4 [原子類](#54-原子類)
- 5.5 [ThreadLocal](#55-threadlocal)
6. [并發工具類](#六并發工具類)
- 6.1 [CountDownLatch](#61-countdownlatch)
- 6.2 [CyclicBarrier](#62-cyclicbarrier)
- 6.3 [Semaphore](#63-semaphore)
7. [線程池技術](#七線程池技術)
- 7.1 [Executor框架](#71-executor框架)
- 7.2 [ThreadPoolExecutor](#72-threadpoolexecutor)
- 7.3 [合理配置線程池](#73-合理配置線程池)
8. [實際應用場景](#八實際應用場景)
- 8.1 [高并發計數器](#81-高并發計數器)
- 8.2 [生產者消費者模式](#82-生產者消費者模式)
9. [總結與最佳實踐](#九總結與最佳實踐)
## 一、多線程基礎概念
### 1.1 什么是線程
線程是操作系統能夠進行運算調度的最小單位,被包含在進程之中,是進程中的實際運作單位。在Java中,每個線程都擁有獨立的程序計數器、虛擬機棧和本地方法棧,但共享堆內存和方法區資源。
```java
// 最簡單的線程示例
Thread thread = new Thread(() -> {
System.out.println("線程執行中...");
});
thread.start();
| 對比維度 | 進程 | 線程 |
|---|---|---|
| 資源占用 | 獨立內存空間 | 共享進程內存 |
| 創建開銷 | 較大(需分配系統資源) | 較小 |
| 通信方式 | 管道、信號、套接字等 | 共享變量 |
| 穩定性 | 一個崩潰不影響其他進程 | 一個崩潰可能導致進程終止 |
class MyThread extends Thread {
@Override
public void run() {
System.out.println("繼承Thread類實現的線程");
}
}
// 使用方式
new MyThread().start();
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("實現Runnable接口的線程");
}
}
// 使用方式
new Thread(new MyRunnable()).start();
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "帶返回值的線程";
}
}
// 使用方式
FutureTask<String> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
System.out.println(task.get()); // 獲取返回值
| 實現方式 | 優點 | 缺點 |
|---|---|---|
| 繼承Thread | 編碼簡單 | 無法繼承其他類 |
| 實現Runnable | 可繼承其他類,更靈活 | 無返回值 |
| 實現Callable | 可獲取返回值,支持異常 | 使用稍復雜 |
stateDiagram
[*] --> NEW
NEW --> RUNNABLE: start()
RUNNABLE --> BLOCKED: 等待同步鎖
BLOCKED --> RUNNABLE: 獲取鎖
RUNNABLE --> WTING: wait()/join()
WTING --> RUNNABLE: notify()/notifyAll()
RUNNABLE --> TIMED_WTING: sleep(n)/wait(n)
TIMED_WTING --> RUNNABLE: 超時結束
RUNNABLE --> TERMINATED: run()結束
// 非原子操作示例
private int count = 0;
public void increment() {
count++; // 實際包含讀-改-寫三步操作
}
// 可見性問題示例
boolean flag = true;
// 線程A
new Thread(() -> {
while(flag) {
// 可能永遠循環
}
}).start();
// 線程B
new Thread(() -> {
flag = false;
}).start();
// 指令重排可能導致的問題
int a = 0;
boolean flag = false;
// 線程A
a = 1; // 語句1
flag = true; // 語句2
// 線程B
if(flag) { // 語句3
int i = a; // 語句4
}
// 同步方法
public synchronized void syncMethod() {
// 臨界區代碼
}
// 同步代碼塊
public void syncBlock() {
synchronized(this) {
// 臨界區代碼
}
}
// 靜態方法鎖
public static synchronized void staticSync() {
// 鎖的是Class對象
}
// ReentrantLock使用示例
private final Lock lock = new ReentrantLock();
public void lockExample() {
lock.lock();
try {
// 臨界區代碼
} finally {
lock.unlock();
}
}
// 保證可見性示例
private volatile boolean shutdown;
public void shutdown() {
shutdown = true;
}
public void doWork() {
while(!shutdown) {
// 執行任務
}
}
// AtomicInteger使用示例
private AtomicInteger counter = new AtomicInteger(0);
public void safeIncrement() {
counter.incrementAndGet(); // 原子操作
}
// 線程局部變量示例
private static ThreadLocal<SimpleDateFormat> dateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
public String formatDate(Date date) {
return dateFormat.get().format(date);
}
(由于篇幅限制,后續章節內容將簡要概述,實際完整文章應詳細展開每個技術點)
完整文章建議擴展方向: 1. 每個代碼示例添加詳細注釋 2. 增加性能對比測試數據 3. 補充JMM內存模型原理圖 4. 添加實際項目案例說明 5. 深入分析synchronized鎖升級過程 6. 討論分布式環境下的線程安全問題 “`
注:此大綱結構完整,實際撰寫時需要: 1. 補充更多代碼示例和注釋 2. 添加示意圖和流程圖 3. 插入性能對比表格 4. 增加實際案例解析 5. 每個技術點進行優缺點分析 6. 最終字數通過擴展各小節內容達到6450字左右
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。