Java中wait()與sleep()兩者的不同深入解析
前言
在 Java 多線程編程中,wait()
和 sleep()
是兩個(gè)常見(jiàn)的工具,用于控制線程的執(zhí)行和等待。雖然它們?cè)诿Q和功能上看似相似,但它們的應(yīng)用場(chǎng)景和具體實(shí)現(xiàn)有著明顯的不同。理解這兩者的區(qū)別對(duì)編寫(xiě)穩(wěn)定、高效的并發(fā)程序至關(guān)重要。本文將深入探討 Java 中 wait()
和 sleep()
方法的區(qū)別、它們的使用場(chǎng)景以及它們?cè)诓煌€程管理機(jī)制中的作用。
1. wait() 和 sleep() 的基本定義
wait()
:wait()
方法是對(duì)象類(Object
)中的一個(gè)方法,用于線程在獲取對(duì)象監(jiān)視器鎖(monitor)后,主動(dòng)釋放鎖并進(jìn)入等待狀態(tài),直到被其他線程通過(guò)notify()
或notifyAll()
方法喚醒。wait()
方法必須在同步代碼塊(synchronized
)中調(diào)用,因?yàn)樗婕暗綄?duì)象的監(jiān)視器鎖。sleep()
:sleep()
方法是Thread
類中的靜態(tài)方法,允許當(dāng)前線程進(jìn)入休眠狀態(tài)一段指定的時(shí)間。線程在調(diào)用sleep()
方法后仍然保持對(duì)已獲得的鎖的持有,并不會(huì)釋放鎖。sleep()
通常用于模擬線程的暫停、限速執(zhí)行等場(chǎng)景。
2. wait() 與 sleep() 的主要區(qū)別
2.1 類與調(diào)用方式不同
類:
wait()
是Object
類中的方法。sleep()
是Thread
類中的靜態(tài)方法。
調(diào)用方式:
wait()
必須在同步塊或同步方法中調(diào)用,且必須持有對(duì)象鎖。sleep()
可以在任何地方調(diào)用,無(wú)需持有任何鎖。
2.2 鎖的處理
wait()
:調(diào)用wait()
方法后,線程會(huì)進(jìn)入等待狀態(tài)并釋放所持有的對(duì)象鎖。這允許其他線程可以獲得該對(duì)象的鎖并執(zhí)行相應(yīng)操作,通常用于實(shí)現(xiàn)線程之間的協(xié)調(diào)和通信。sleep()
:調(diào)用sleep()
方法后,線程會(huì)進(jìn)入休眠狀態(tài),但它不會(huì)釋放所持有的鎖。這意味著其他線程依然無(wú)法訪問(wèn)同步塊中的共享資源,直到休眠結(jié)束。
2.3 喚醒機(jī)制
wait()
:線程調(diào)用wait()
后,需要被其他線程調(diào)用notify()
或notifyAll()
方法來(lái)顯式喚醒。wait()
主要用于實(shí)現(xiàn)線程之間的通信與協(xié)作。sleep()
:線程調(diào)用sleep()
后,不需要顯式的喚醒。它會(huì)在指定的時(shí)間后自動(dòng)喚醒并繼續(xù)執(zhí)行代碼。sleep()
通常用于暫時(shí)停止當(dāng)前線程,模擬計(jì)時(shí)器功能或節(jié)省資源。
2.4 線程狀態(tài)的不同
wait()
:調(diào)用wait()
方法后,線程會(huì)進(jìn)入等待池(waiting pool),直到有其他線程調(diào)用notify()
或notifyAll()
將其喚醒。sleep()
:調(diào)用sleep()
方法后,線程進(jìn)入計(jì)時(shí)等待(timed waiting)狀態(tài),時(shí)間到了之后會(huì)自動(dòng)回到就緒狀態(tài)(ready state)。
2.5 發(fā)生的異常
wait()
:wait()
可能拋出InterruptedException
,因此必須在代碼中進(jìn)行捕獲。sleep()
:sleep()
也會(huì)拋出InterruptedException
,因?yàn)樾菝咂陂g線程可能被中斷,同樣需要進(jìn)行異常處理。
3. 使用場(chǎng)景對(duì)比
wait()
通常用于需要線程之間進(jìn)行通信和協(xié)調(diào)的場(chǎng)景。例如,當(dāng)一個(gè)線程需要等待某個(gè)條件滿足才能繼續(xù)執(zhí)行時(shí),wait()
方法就非常合適。sleep()
通常用于讓線程暫停一段時(shí)間,例如模擬延遲,限速執(zhí)行或者實(shí)現(xiàn)周期性任務(wù)。在sleep()
過(guò)程中,線程并不釋放所持有的資源鎖,這意味著它不會(huì)對(duì)共享資源的可見(jiàn)性造成影響。
4. 實(shí)際代碼示例
wait() 使用示例
以下是一個(gè)生產(chǎn)者-消費(fèi)者問(wèn)題中 wait()
和 notify()
的使用示例:
public class WaitNotifyExample { private static final Object lock = new Object(); private static boolean condition = false; public static void main(String[] args) { Thread producer = new Thread(() -> { synchronized (lock) { condition = true; System.out.println("Producer produced an item"); lock.notify(); // 喚醒消費(fèi)者 } }); Thread consumer = new Thread(() -> { synchronized (lock) { while (!condition) { try { System.out.println("Consumer is waiting for the item..."); lock.wait(); // 等待生產(chǎn)者喚醒 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Consumer consumed the item"); } }); consumer.start(); producer.start(); } }
在上面的代碼中,消費(fèi)者線程在等待生產(chǎn)者提供商品,調(diào)用 wait()
方法進(jìn)入等待狀態(tài),生產(chǎn)者完成任務(wù)后調(diào)用 notify()
來(lái)喚醒消費(fèi)者。
sleep() 使用示例
以下是一個(gè)使用 sleep()
來(lái)模擬線程暫停的例子:
public class SleepExample { public static void main(String[] args) { Thread thread = new Thread(() -> { try { System.out.println("Thread is going to sleep for 2 seconds"); Thread.sleep(2000); // 暫停 2 秒 System.out.println("Thread woke up"); } catch (InterruptedException e) { e.printStackTrace(); } }); thread.start(); } }
在這個(gè)示例中,線程調(diào)用 sleep(2000)
方法后,暫停執(zhí)行 2 秒后自動(dòng)喚醒繼續(xù)執(zhí)行。
5. wait() 與 sleep() 的注意事項(xiàng)
使用
wait()
必須加鎖:wait()
方法必須在同步塊中使用,必須先持有對(duì)象鎖。否則會(huì)拋出IllegalMonitorStateException
。防止過(guò)長(zhǎng)鎖定:
sleep()
不釋放已持有的鎖,因此在鎖定時(shí)長(zhǎng)較長(zhǎng)的場(chǎng)景下使用sleep()
可能會(huì)導(dǎo)致其他線程無(wú)法獲取鎖,影響并發(fā)效率。中斷處理:
wait()
和sleep()
都可能被中斷,調(diào)用這些方法的代碼必須處理InterruptedException
,這在編寫(xiě)并發(fā)程序時(shí)尤為重要。
6. 小結(jié)
Java 中的 wait()
和 sleep()
方法雖然在功能上都可以使線程暫時(shí)停止執(zhí)行,但它們有著顯著的區(qū)別和不同的應(yīng)用場(chǎng)景:
wait()
是對(duì)象級(jí)別的方法,必須在同步塊中使用,調(diào)用后會(huì)釋放對(duì)象的鎖,通常用于實(shí)現(xiàn)線程之間的通信與協(xié)調(diào)。sleep()
是線程級(jí)別的方法,調(diào)用后線程進(jìn)入休眠狀態(tài)但不會(huì)釋放已持有的鎖,適合用于模擬延遲或限速執(zhí)行。
正確理解和使用 wait()
與 sleep()
可以幫助開(kāi)發(fā)者更好地控制線程的執(zhí)行順序,避免常見(jiàn)的并發(fā)問(wèn)題。尤其是在實(shí)現(xiàn)復(fù)雜的多線程應(yīng)用時(shí),了解它們的區(qū)別和使用場(chǎng)景能夠顯著提升程序的穩(wěn)定性和性能。
總結(jié)
到此這篇關(guān)于Java中wait()與sleep()兩者的不同深入解析的文章就介紹到這了,更多相關(guān)Java wait()與sleep()的不同內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(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有參及無(wú)參區(qū)別)
- java sleep()和wait()的區(qū)別點(diǎn)總結(jié)
- Java詳細(xì)分析sleep和wait方法有哪些區(qū)別
- java面試突擊之sleep和wait有什么區(qū)別詳析
相關(guān)文章
java 動(dòng)態(tài)加載的實(shí)現(xiàn)代碼
這篇文章主要介紹了java 動(dòng)態(tài)加載的實(shí)現(xiàn)代碼的相關(guān)資料,Java動(dòng)態(tài)加載類主要是為了不改變主程序代碼,通過(guò)修改配置文件就可以操作不同的對(duì)象執(zhí)行不同的功能,需要的朋友可以參考下2017-07-07對(duì)handlerexecutionchain類的深入理解
下面小編就為大家?guī)?lái)一篇對(duì)handlerexecutionchain類的深入理解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07SpringBoot項(xiàng)目修改訪問(wèn)端口和訪問(wèn)路徑的方法
這篇文章主要介紹了SpringBoot項(xiàng)目修改訪問(wèn)端口和訪問(wèn)路徑的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12MyBatis環(huán)境資源配置實(shí)現(xiàn)代碼詳解
這篇文章主要介紹了MyBatis環(huán)境資源配置實(shí)現(xiàn)代碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Java編程之多線程死鎖與線程間通信簡(jiǎn)單實(shí)現(xiàn)代碼
這篇文章主要介紹了Java編程之多線程死鎖與線程間通信簡(jiǎn)單實(shí)現(xiàn)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10關(guān)于Spring Actuator的簡(jiǎn)單測(cè)試
這篇文章主要介紹了關(guān)于Spring Actuator的簡(jiǎn)單測(cè)試,Spring-Actuator 是spring下的程序監(jiān)控系統(tǒng),通過(guò)簡(jiǎn)單的配置就可以查看程序的相關(guān)信息,本文提供了相關(guān)配置,需要的朋友可以參考下2023-10-10java中為什么要謹(jǐn)慎使用Arrays.asList、ArrayList的subList
這篇文章主要介紹了java中為什么要謹(jǐn)慎使用Arrays.asList、ArrayList的subList,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02MyBatis Plus更新對(duì)象無(wú)法設(shè)空值解決方案
這篇文章主要介紹了MyBatis Plus更新對(duì)象無(wú)法設(shè)空值解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11