hello啊,各位觀眾姥爺們!!!本baby今天來報道了!哈哈哈哈哈嗝🐶
面試官:說說sleep和wait的區別?
1. 核心區別總結
特性 | sleep() | wait() |
---|---|---|
所屬類 | Thread 類的靜態方法 | Object 類的實例方法 |
鎖的釋放 | 不釋放鎖(保持當前線程持有的鎖) | 釋放鎖(讓其他線程獲取鎖) |
調用條件 | 可在任何地方調用 | 必須在 synchronized 同步塊或方法中調用 |
喚醒機制 | 時間到自動喚醒 | 需其他線程調用 notify() /notifyAll() |
作用范圍 | 控制線程休眠 | 用于線程間通信(協調共享資源訪問) |
異常處理 | 需捕獲 InterruptedException | 需捕獲 InterruptedException |
2. 詳細對比
(1) 鎖的行為
-
sleep()
線程調用sleep()
后進入休眠狀態,但不會釋放已持有的鎖。其他線程無法獲取該鎖,可能導致阻塞。synchronized (lock) {Thread.sleep(1000); // 持有鎖休眠,其他線程無法進入同步塊 }
-
wait()
調用wait()
會立即釋放當前對象的鎖,允許其他線程獲取鎖并執行同步代碼塊。synchronized (lock) {lock.wait(); // 釋放鎖,其他線程可進入同步塊 }
(2) 使用場景
-
sleep()
用于讓線程暫停執行一段時間(如定時任務、模擬延遲)。// 定時任務:每秒執行一次 while (true) {doTask();Thread.sleep(1000); // 休眠 1 秒 }
-
wait()
用于線程間協作,等待某個條件滿足(如生產者-消費者模型)。// 消費者等待隊列非空 synchronized (queue) {while (queue.isEmpty()) {queue.wait(); // 釋放鎖,等待生產者通知}queue.poll(); }
(3) 喚醒機制
-
sleep()
休眠時間結束后自動恢復,或通過interrupt()
中斷休眠(拋出InterruptedException
)。 -
wait()
必須由其他線程調用同一對象的notify()
或notifyAll()
喚醒,或等待超時(若指定了時間)。
3. 代碼示例
sleep()
示例
public class SleepDemo {public static void main(String[] args) {new Thread(() -> {synchronized (SleepDemo.class) {System.out.println("線程 A 獲取鎖,開始休眠 3 秒");try {Thread.sleep(3000); // 休眠但不釋放鎖} catch (InterruptedException e) {e.printStackTrace();}System.out.println("線程 A 喚醒");}}).start();new Thread(() -> {synchronized (SleepDemo.class) {System.out.println("線程 B 獲取鎖");}}).start();}
}
輸出:
線程 A 獲取鎖,開始休眠 3 秒
(等待 3 秒后)
線程 A 喚醒
線程 B 獲取鎖
現象:線程 B 必須等待線程 A 釋放鎖后才能執行。
wait()
示例
public class WaitDemo {public static void main(String[] args) {Object lock = new Object();new Thread(() -> {synchronized (lock) {System.out.println("線程 A 獲取鎖,并等待");try {lock.wait(); // 釋放鎖} catch (InterruptedException e) {e.printStackTrace();}System.out.println("線程 A 被喚醒");}}).start();new Thread(() -> {synchronized (lock) {System.out.println("線程 B 獲取鎖,喚醒線程 A");lock.notify();}}).start();}
}
輸出:
線程 A 獲取鎖,并等待
線程 B 獲取鎖,喚醒線程 A
線程 A 被喚醒
現象:線程 A 調用
wait()
后釋放鎖,線程 B 可以獲取鎖并喚醒線程 A。
4. 常見問題與注意事項
-
為什么
wait()
必須在同步塊中調用?wait()
和notify()
依賴于對象的監視器鎖(Monitor),調用前必須獲取鎖,否則拋出IllegalMonitorStateException
。- 這是為了避免競態條件(Race Condition),確保線程在安全狀態下等待或喚醒。
-
sleep()
是否會釋放鎖?- 不會。
sleep()
是線程自身的行為,與鎖無關。
- 不會。
-
如何選擇
sleep()
和wait()
?- 需要暫停線程但不涉及鎖協調 →
sleep()
。 - 需要線程間協作并釋放鎖 →
wait()
+notify()
。
- 需要暫停線程但不涉及鎖協調 →
-
避免死鎖:
- 若線程調用
wait()
后未被喚醒,將永久阻塞。確保邏輯中始終有喚醒機制。
- 若線程調用
總結
sleep()
:單純讓線程休眠,不涉及鎖協調,適用于定時任務或延遲操作。wait()
:用于線程間通信,需與notify()
配合,確保共享資源的安全訪問。- 核心區別:
sleep()
不釋放鎖,wait()
釋放鎖。