關(guān)于 sleep 和 wait 深度對(duì)比!
在計(jì)算機(jī)編程中,特別是在多線程或并發(fā)編程中,sleep 和 wait 是兩個(gè)非常常見的函數(shù),但它們有不同的用途和工作機(jī)制,這篇文章我們將詳細(xì)地討論 sleep 和 wait 的區(qū)別,包括它們的內(nèi)部工作原理、應(yīng)用場(chǎng)景以及詳細(xì)的示例代碼,以幫助更全面地理解它們。
sleep
工作機(jī)制:
- 暫停當(dāng)前線程: sleep 方法暫停當(dāng)前執(zhí)行的線程一段指定的時(shí)間,時(shí)間結(jié)束后線程再恢復(fù)執(zhí)行。
- 不會(huì)釋放鎖: 即使線程在 sleep 狀態(tài)下持有鎖,它也不會(huì)釋放。它依然占用著該鎖,其他線程無法獲得該鎖。
- 線程狀態(tài)轉(zhuǎn)換: sleep 方法會(huì)使線程從運(yùn)行(RUNNING)狀態(tài)轉(zhuǎn)換為計(jì)時(shí)等待(TIMED_WAITING)狀態(tài)。
- 靜態(tài)方法: 它是 Thread 類的靜態(tài)方法,調(diào)用時(shí)通過 Thread.sleep 訪問。
應(yīng)用場(chǎng)景:
- 限流: 控制任務(wù)執(zhí)行的頻率,防止線程過度占用CPU資源。
- 定時(shí)任務(wù): 在某個(gè)循環(huán)中,定時(shí)執(zhí)行某些任務(wù)。
示例代碼:
public class SleepExample extends Thread {
public void run() {
try {
System.out.println("Thread going to sleep for 2 seconds.");
Thread.sleep(2000); // 睡眠 2 秒
System.out.println("Thread woke up after sleeping.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SleepExample thread = new SleepExample();
thread.start();
}
}
wait
工作機(jī)制:
- 釋放鎖并等待通知: wait 方法使當(dāng)前線程等待,直到其他線程調(diào)用當(dāng)前對(duì)象的 notify 或 notifyAll 方法。調(diào)用 wait 時(shí),線程會(huì)釋放它持有的鎖。
- 必須在同步塊或同步方法中使用: wait 方法必須在同步塊或同步方法中調(diào)用,否則會(huì)拋出 IllegalMonitorStateException。
- 線程狀態(tài)轉(zhuǎn)換: wait 方法會(huì)使線程從運(yùn)行(RUNNING)狀態(tài)轉(zhuǎn)換為等待(WAITING)狀態(tài)。
- 對(duì)象方法: 它是 Object 類的方法,所以任何對(duì)象都可以調(diào)用。
應(yīng)用場(chǎng)景:
- 線程間通信: 多個(gè)線程協(xié)同工作時(shí),一個(gè)線程等待某個(gè)條件滿足后,再被其他線程通知繼續(xù)執(zhí)行。
- 生產(chǎn)者-消費(fèi)者模型: 經(jīng)常用于實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模式中的同步。
示例代碼:
public class WaitNotifyExample {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
// 等待線程
Thread waitingThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread waiting for the lock to be released.");
lock.wait(); // 進(jìn)入等待狀態(tài)并釋放鎖
System.out.println("Thread resumed after lock released.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 通知線程
Thread notifyingThread = new Thread(() -> {
synchronized (lock) {
System.out.println("Notifying other threads.");
lock.notify(); // 通知其他等待該鎖的線程
System.out.println("Notified waiting thread.");
}
});
waitingThread.start();
Thread.sleep(1000); // 確保 waitingThread 先持有鎖并進(jìn)入等待狀態(tài)
notifyingThread.start();
}
}
sleep 和 wait的對(duì)比
特性 | sleep | wait |
釋放鎖 | 否 | 是 |
需要在同步塊或方法中 | 否 | 是 |
屬于 | Thread 類 | Object 類 |
引發(fā)異常 | InterruptedException | InterruptedException 引發(fā)機(jī)制相同 |
作用范圍 | 當(dāng)前調(diào)用的線程 | 當(dāng)前擁有鎖的線程 |
線程狀態(tài)改變 | 變?yōu)橛?jì)時(shí)等待(TIMED_WAITING) | 變?yōu)榈却╓AITING) |
典型應(yīng)用場(chǎng)景 | 暫停線程的一段時(shí)間,用于控制節(jié)奏或定時(shí)操作 | 線程間通信,生產(chǎn)者-消費(fèi)者模型等 |
總結(jié)
本文,我們分析了sleep 和 wait,sleep用于暫停當(dāng)前線程一段指定時(shí)間,但仍保持鎖,這常用來控制執(zhí)行節(jié)奏或定時(shí)操作。wait使線程釋放鎖并進(jìn)入等待狀態(tài),直到通過 notify/notifyAll 被喚醒,需在同步塊中使用,適用于線程間通信如生產(chǎn)者-消費(fèi)者模型。