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

Java 線程 sleep() 與 wait() 深度對比:鎖行為、喚醒機制與實戰陷阱

     編輯:Java 相關知識

核心差異一覽表

維度sleep()wait()
所屬類Thread (static)Object
鎖行為不釋放鎖釋放鎖
喚醒方式時間到期自動喚醒notify()/notifyAll() 或超時
調用前提無必須在 synchronized 塊/方法中
異常處理InterruptedExceptionInterruptedException + IllegalMonitorStateException(非同步塊調用)

sleep() 實戰演示:鎖不釋放導致併發阻塞

class ThreadSleep implements Runnable {
    int count = 0;
    public void run() { count(); }
    public void count() {
        while (count < 20) {
            synchronized (this) { // 加鎖
                System.out.println(Thread.currentThread().getName() + " count=" + count);
                count++;
                try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); }
            }
        }
    }
}
// 輸出:線程甲獨佔執行 0~19,線程乙全程等待鎖釋放

現象:sleep(100) 期間鎖未釋放,另一線程無法進入同步塊,導致併發度為 0。

wait() 實戰演示:釋放鎖實現真正併發

public void count() {
    while (count < 20) {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + " count=" + count);
            count++;
            try { this.wait(100); } catch (Exception e) { e.printStackTrace(); }
        }
    }
}
// 輸出:線程甲、乙交替執行,鎖在 wait 期間被釋放

關鍵點:wait(100) 相當於 wait() + 超時自動喚醒,且釋放鎖,其他線程可獲取鎖繼續執行。

wait/notify 經典協作模式:生產者-消費者

class SharedBuffer {
    private final List<Integer> buffer = new ArrayList<>();
    private final int capacity = 5;

    public synchronized void produce(int value) throws InterruptedException {
        while (buffer.size() == capacity) wait(); // 滿了等待
        buffer.add(value);
        notifyAll(); // 喚醒消費者
    }

    public synchronized int consume() throws InterruptedException {
        while (buffer.isEmpty()) wait(); // 空了等待
        int value = buffer.remove(0);
        notifyAll(); // 喚醒生產者
        return value;
    }
}

常見坑點與最佳實踐

  1. 永遠在循環中調用 wait():防止虛假喚醒(spurious wakeup)。
    while (conditionNotMet) wait(); // 而非 if
  2. 優先使用 notifyAll():除非確定只有一類線程等待,否則 notify() 可能喚醒錯誤線程導致活鎖。
  3. sleep 用於單純延遲,wait 用於線程協作——不要混淆場景。
  4. InterruptedException 處理:不要吞掉中斷,至少恢復中斷狀態 Thread.currentThread().interrupt() 或拋出。

總結

sleep() 是「暫停當前線程,鎖不放」;wait() 是「進入等待集,鎖釋放,等通知」。理解鎖所有權轉移是掌握兩者本質區別的鑰匙。實際開發中,併發包(java.util.concurrent)提供的 Condition、BlockingQueue、CountDownLatch 等高級工具往往比裸露的 wait/notify 更安全、更易維護——能用高級 API 就別手寫底層協作。

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