首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

深入淺出 Java 多線程:從基礎概念到同步機制與線程池實戰

     編輯:Java 綜合教學

一、核心概念辨析

進程 vs 線程

  • 進程:資源分配單位(獨立內存空間、文件句柄),包含一個或多個線程。
  • 線程:CPU 調度單位,最小執行單元。同進程線程共享堆/方法區,私有棧/程序計數器。
  • 類比:進程=工廠,線程=工人。工人共享工廠資源(倉庫、設備),各自有工具箱(棧)。

線程交互:互斥與同步

  • 互斥:同一時刻只有一個線程訪問共享資源(加鎖)。
  • 同步:線程間協作,按順序執行(wait/notify)。

二、線程生命周期與狀態轉換

線程生命周期圖

線程狀態轉換圖

狀態說明觸發條件
NEW新建new Thread()
RUNNABLE就緒/運行start()、獲得 CPU、yield()、鎖釋放
BLOCKED阻塞sleep()、wait()、I/O、同步鎖等待
TERMINATED死亡run() 結束、異常退出
阻塞三類型:等待阻塞、同步阻塞、其他阻塞(sleep/join/I/O)。

三、線程調度與常用操作

1. 優先級

static int MAX_PRIORITY = 10;
static int MIN_PRIORITY = 1;
static int NORM_PRIORITY = 5;
thread.setPriority(Thread.MAX_PRIORITY);

優先級只是提示,不保證執行順序,受平台影響大。

2. 睡眠

Thread.sleep(1000); // 釋放 CPU,保持鎖,到期進入 RUNNABLE

3. 等待/通知

synchronized(obj) {
    obj.wait();      // 釋放鎖,進入 WAITING
    obj.notify();    // 喚醒一個
    obj.notifyAll(); // 喚醒全部
}
必須在同步塊/方法中調用,否則拋 IllegalMonitorStateException。

4. 讓步

Thread.yield(); // RUNNABLE → RUNNABLE,同優先級可能獲得 CPU

5. 合併

thread.join(); // 當前線程阻塞,等待 thread 結束

6. 守護線程

thread.setDaemon(true); // JVM 退出時不等待守護線程(如 GC)

四、創建線程兩種方式

1. 繼承 Thread

class Actor extends Thread {
    @Override public void run() { /* 任務邏輯 */ }
}
new Actor().start();

2. 實現 Runnable(推薦)

class Actress implements Runnable {
    @Override public void run() { /* 任務邏輯 */ }
}
new Thread(new Actress()).start();

優勢:避免單繼承限制;任務與線程分離,利於線程池復用。

五、線程安全停止

錯誤方式

  • stop():強制殺死,數據不一致、鎖未釋放(已棄用)。
  • interrupt() 單純調用:僅設置中斷標志,線程繼續跑。

正確方式:volatile 標志位

class Worker extends Thread {
    volatile boolean running = true;
    @Override public void run() {
        while (running) { /* 業務邏輯 */ }
    }
    public void shutdown() { running = false; }
}

interrupt 配合 isInterrupted

while (!Thread.currentThread().isInterrupted()) { /* ... */ }
// 外部調用 thread.interrupt() 設置標志,循環檢測退出
陷阱:若線程處於 sleep()/wait(),調用 interrupt() 會清除中斷標志並拋 InterruptedException,需捕獲後重新設置或拋出。

六、同步與鎖機制

synchronized 關鍵字

// 同步方法
public synchronized void add() { /* ... */ }

// 同步代碼塊(指定鎖對象)
public void add() {
    synchronized (lockObj) { /* ... */ }
}

鎖核心規則

  1. 每個對象一把鎖(this 或 Class 對象)。
  2. 同步方法/塊執行前獲取鎖,退出釋放鎖。
  3. 靜態同步鎖住 Class 對象,非靜態鎖住實例,互不干擾。
  4. sleep() 不釋放鎖;wait() 釋放鎖。

生產者-消費者經典模型

class Buffer {
    List<Integer> list = new ArrayList<>();
    int capacity = 10;

    public synchronized void produce(int v) throws InterruptedException {
        while (list.size() == capacity) wait();
        list.add(v);
        notifyAll();
    }

    public synchronized int consume() throws InterruptedException {
        while (list.isEmpty()) wait();
        int v = list.remove(0);
        notifyAll();
        return v;
    }
}

七、WaitSet 與同步底層

WaitSet 示意圖

  • 每個鎖對象關聯一個 EntrySet(爭搶鎖隊列)和 WaitSet(調用 wait 進入)。
  • notify() 隨機移動一個線程從 WaitSet → EntrySet;notifyAll() 全部移動。
  • 線程必須重新獲得鎖才能從 EntrySet 進入 Critical Section。

八、進階學習路線

  1. JMM:happens-before、volatile、final、指令重排。
  2. Lock & Condition:ReentrantLock、ReadWriteLock、Condition.await/signal。
  3. 原子類:AtomicInteger、CAS、ABA 問題。
  4. 線程池:ExecutorService、ThreadPoolExecutor、拒絕策略。
  5. 並發容器:ConcurrentHashMap、BlockingQueue、CopyOnWriteArrayList。
  6. 經典模型:生產消費、讀寫鎖、Future、Worker Thread。
  7. 工具類:CountDownLatch、CyclicBarrier、Semaphore、Phaser。

推薦書籍

  • 《Java Concurrency in Practice》—— Brian Goetz
  • 《Core Java 卷 II》—— Cay Horstmann
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved