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

Java 多執行緒核心技術:Thread 建立、同步、等待喚醒與實戰範例

     編輯:Java 程式設計入門

建立執行緒兩種標準方式

方式步驟優缺點
繼承 Thread1. 定義類別 extends Thread
2. 覆寫 run()
3. 建立實例呼叫 start()
簡單直觀,但單繼承限制,無法繼承其他業務類別
實作 Runnable1. 定義類別 implements Runnable
2. 實作 run()
3. new Thread(runnable).start()
避免單繼承限制,任務與執行緒分離,支援線程池複用,推薦

常用 Thread API 速查


// 守護執行緒:所有使用者執行緒結束即自動結束
thread.setDaemon(true);

// 休眠(靜態方法,當前執行緒)
Thread.sleep(100); // ms,拋 InterruptedException

// 中斷標記
thread.interrupt();           // 設定中斷旗標
Thread.interrupted();         // 靜態,檢查並清除當前執行緒中斷狀態
thread.isInterrupted();       // 實例,檢查指定執行緒中斷狀態(不清除)

// 等待/通知(必須在 synchronized 區塊內,持有物件鎖)
obj.wait();       // 釋放鎖並進入等待集合
obj.notify();     // 喚醒單一等待執行緒
obj.notifyAll();  // 喚醒全部等待執行緒

同步機制

synchronized 關鍵字

  • 同步實例方法:鎖 this
  • 同步靜態方法:鎖 ClassName.class
  • 同步區塊:synchronized(lockObj) { ... },可精確控制鎖粒度

核心規則:多執行緒操作共享資料時,必須使用同一把鎖,確保同一時刻僅一執行緒進入臨界區。

售票經典範例


class Tickets implements Runnable {
    private int tick = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {  // 鎖住當前 Runnable 實例
                if (tick > 0) {
                    try { Thread.sleep(100); } catch (InterruptedException ignored) {}
                    System.out.println(Thread.currentThread().getName() + " 售出第 " + tick-- + " 張票");
                } else {
                    break;
                }
            }
        }
    }
}

// 測試
public class Test {
    public static void main(String[] args) {
        Tickets task = new Tickets();
        new Thread(task, "窗口A").start();
        new Thread(task, "窗口B").start();
        new Thread(task, "窗口C").start();
    }
}

等待喚醒機制:生產者-消費者模型


class Storage {
    private int count = 0;
    private final int MAX = 10;

    public synchronized void produce() {
        while (count >= MAX) {
            try { wait(); } catch (InterruptedException ignored) {}
        }
        count++;
        System.out.println(Thread.currentThread().getName() + " 生產,庫存=" + count);
        notifyAll();
    }

    public synchronized void consume() {
        while (count <= 0) {
            try { wait(); } catch (InterruptedException ignored) {}
        }
        count--;
        System.out.println(Thread.currentThread().getName() + " 消費,庫存=" + count);
        notifyAll();
    }
}

關鍵點:

  1. wait()/notify() 必須在 同一把鎖 上呼叫。
  2. 使用 while 而非 if 判斷條件(防止虛假喚醒)。
  3. 狀態改變後呼叫 notifyAll() 確保所有等待方重新檢查條件。

進階替代方案(JDK 5+ 推薦)

需求現代 API優勢
鎖與條件變數ReentrantLock + Condition可中斷鎖、公平鎖、多條件變數、嘗試鎖定
執行緒池管理ExecutorService / ThreadPoolExecutor生命週期管理、工作隊列、拒絕策略、監控指標
非同步計算結果CompletableFuture / Future鏈式組合、異常傳播、多任務協調
高併發計數/累加LongAdder / AtomicLong無鎖 CAS,高吞吐
執行緒安全集合ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue細粒度鎖/無鎖,效能優於同步包裝器

總結

掌握 Runnable + 線程池作為基礎範式;
用 synchronized 解決簡單同步,複雜場景升級 Lock/Condition;
等待喚醒牢記「同一把鎖、while 循環、notifyAll」;
實務中優先使用 java.util.concurrent 成熟組件,避免手工造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved