java面試突擊之sleep和wait有什么區(qū)別詳析
前言
sleep 方法和 wait 方法都是用來將線程進(jìn)入休眠狀態(tài)的,并且 sleep 和 wait 方法都可以響應(yīng) interrupt 中斷,也就是線程在休眠的過程中,如果收到中斷信號,都可以進(jìn)行響應(yīng),并拋出 InterruptedException 異常。那 sleep 和 wait 的區(qū)別都有哪些呢?接下來,我們一起來看。
區(qū)別一:語法使用不同
wait 方法必須配合 synchronized 一起使用,不然在運(yùn)行時(shí)就會拋出 IllegalMonitorStateException 的異常,如下代碼所示:

初看代碼好像沒啥問題,編譯器也沒報(bào)錯,然而當(dāng)我們運(yùn)行以上程序時(shí)就會發(fā)生如下錯誤:

而 sleep 可以單獨(dú)使用,無需配合 synchronized 一起使用。
區(qū)別二:所屬類不同
wait 方法屬于 Object 類的方法,而 sleep 屬于 Thread 類的方法,如下圖所示:

區(qū)別三:喚醒方式不同
sleep 方法必須要傳遞一個(gè)超時(shí)時(shí)間的參數(shù),且過了超時(shí)時(shí)間之后,線程會自動喚醒。而 wait 方法可以不傳遞任何參數(shù),不傳遞任何參數(shù)時(shí)表示永久休眠,直到另一個(gè)線程調(diào)用了 notify 或 notifyAll 之后,休眠的線程才能被喚醒。也就是說 sleep 方法具有主動喚醒功能,而不傳遞任何參數(shù)的 wait 方法只能被動的被喚醒。
區(qū)別四:釋放鎖資源不同
wait 方法會主動的釋放鎖,而 sleep 方法則不會。接下來我們使用代碼的方式來演示一下二者的區(qū)別。
sleep 不釋放鎖
接下來使用 sleep 是線程休眠 2s,然后在另一個(gè)線程中嘗試獲取公共鎖,如果能夠獲取到鎖,則說明 sleep 在休眠時(shí)會釋放鎖,反之則說明不會釋放鎖,實(shí)現(xiàn)代碼如下:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
System.out.println("新線程獲取到鎖:" + LocalDateTime.now());
try {
// 休眠 2s
Thread.sleep(2000);
System.out.println("新線程獲釋放鎖:" + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 等新線程先獲得鎖
Thread.sleep(200);
System.out.println("主線程嘗試獲取鎖:" + LocalDateTime.now());
// 在新線程休眠之后,嘗試獲取鎖
synchronized (lock) {
System.out.println("主線程獲取到鎖:" + LocalDateTime.now());
}
}以上代碼的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,在調(diào)用了 sleep 之后,在主線程里嘗試獲取鎖卻沒有成功,只有 sleep 執(zhí)行完之后釋放了鎖,主線程才正常的得到了鎖,這說明 sleep 在休眠時(shí)并不會釋放鎖。
wait 釋放鎖
接下來使用同樣的方式,將 sleep 替換成 wait,在線程休眠之后,在另一個(gè)線程中嘗試獲取鎖,實(shí)現(xiàn)代碼如下:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
System.out.println("新線程獲取到鎖:" + LocalDateTime.now());
try {
// 休眠 2s
lock.wait(2000);
System.out.println("新線程獲釋放鎖:" + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 等新線程先獲得鎖
Thread.sleep(200);
System.out.println("主線程嘗試獲取鎖:" + LocalDateTime.now());
// 在新線程休眠之后,嘗試獲取鎖
synchronized (lock) {
System.out.println("主線程獲取到鎖:" + LocalDateTime.now());
}
}以上代碼的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,當(dāng)調(diào)用了 wait 之后,主線程立馬嘗試獲取鎖成功了,這就說明 wait 休眠時(shí)是釋放鎖的。
區(qū)別五:線程進(jìn)入狀態(tài)不同
調(diào)用 sleep 方法線程會進(jìn)入 TIMED_WAITING 有時(shí)限等待狀態(tài),而調(diào)用無參數(shù)的 wait 方法,線程會進(jìn)入 WAITING 無時(shí)限等待狀態(tài)。代碼演示:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
// 休眠 2s
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
Thread.sleep(200);
System.out.println("wait() 之后進(jìn)入狀態(tài):" + t1.getState());
System.out.println("sleep(2000) 之后進(jìn)入狀態(tài):" + t2.getState());
}以上代碼的執(zhí)行結(jié)果如下:

總結(jié)
sleep 和 wait 都可以讓線程進(jìn)入休眠狀態(tài),并且它們都可以響應(yīng) interrupt 中斷,但二者的區(qū)別主要體現(xiàn)在:語法使用不同、所屬類不同、喚醒方式不同、釋放鎖不同和線程進(jìn)入的狀態(tài)不同。
到此這篇關(guān)于java面試突擊之sleep和wait區(qū)別的文章就介紹到這了,更多相關(guān)java sleep和wait區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中sleep方法和wait方法的五個(gè)區(qū)別
- Java線程中sleep和wait的區(qū)別詳細(xì)介紹
- Java中sleep()與wait()的區(qū)別總結(jié)
- Java面試題篇之Sleep()方法與Wait()方法的區(qū)別詳解
- 詳解Java中wait和sleep的區(qū)別
- 詳解Java中的sleep()和wait()的區(qū)別
- Java中wait與sleep的區(qū)別講解(wait有參及無參區(qū)別)
- java sleep()和wait()的區(qū)別點(diǎn)總結(jié)
- Java詳細(xì)分析sleep和wait方法有哪些區(qū)別
- Java中wait()與sleep()兩者的不同深入解析
相關(guān)文章
java利用多線程和Socket實(shí)現(xiàn)猜拳游戲
這篇文章主要為大家詳細(xì)介紹了java利用多線程和Socket實(shí)現(xiàn)猜拳游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
Spring Boot實(shí)現(xiàn)異步請求(Servlet 3.0)
在spring 3.2 及以后版本中增加了對請求的異步處理,這篇文章主要介紹了Spring Boot實(shí)現(xiàn)異步請求(Servlet 3.0),感興趣的小伙伴們可以參考一下。2017-04-04
Spring如何集成ibatis項(xiàng)目并實(shí)現(xiàn)dao層基類封裝
這篇文章主要介紹了Spring如何集成ibatis項(xiàng)目并實(shí)現(xiàn)dao層基類封裝,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Java 判斷字符串a(chǎn)和b是否互為旋轉(zhuǎn)詞
本篇文章主要介紹了判斷字符串a(chǎn)和b是否互為旋轉(zhuǎn)詞的相關(guān)知識,具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-05-05
最新log4j2遠(yuǎn)程代碼執(zhí)行漏洞(附解決方法)
Apache?Log4j2?遠(yuǎn)程代碼執(zhí)行漏洞攻擊代碼,該漏洞利用無需特殊配置,經(jīng)多方驗(yàn)證,Apache?Struts2、Apache?Solr、Apache?Druid、Apache?Flink等均受影響,本文就介紹一下解決方法2021-12-12

