Java詳細(xì)分析sleep和wait方法有哪些區(qū)別
一、sleep和wait方法的區(qū)別
- 根本區(qū)別:sleep是Thread類中的方法,不會(huì)馬上進(jìn)入運(yùn)行狀態(tài),wait是Object類中的方法,一旦一個(gè)對(duì)象調(diào)用了wait方法,必須要采用notify()和notifyAll()方法喚醒該進(jìn)程
- 釋放同步鎖:sleep會(huì)釋放cpu,但是sleep不會(huì)釋放同步鎖的資源,wait會(huì)釋放同步鎖資源
- 使用范圍: sleep可以在任何地方使用,但wait只能在synchronized的同步方法或是代碼塊中使用
- 異常處理: sleep需要捕獲異常,而wait不需要捕獲異常
二、wait方法
- 使當(dāng)前執(zhí)行代碼的線程進(jìn)行等待. (把線程放到等待隊(duì)列中)
- 釋放當(dāng)前的鎖
- 滿足一定條件時(shí)被喚醒, 重新嘗試獲取這個(gè)鎖.
- wait 要搭配 synchronized 來(lái)使用,脫離 synchronized 使用 wait 會(huì)直接拋出異常.
wait方法的使用
wait方法
/** * wait的使用 */ public class WaitDemo1 { public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(() -> { System.out.println("線程1開(kāi)始執(zhí)行"); try { synchronized (lock) { System.out.println("線程1調(diào)用wait方法...."); // 無(wú)限期的等待狀態(tài) lock.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程1執(zhí)行完成"); }, "線程1"); t1.start(); } }
有參wait線程和無(wú)參wait線程
/** * 有參wait線程和無(wú)參wait線程 */ public class WaitDemo2 { public static void main(String[] args) { Object lock1 = new Object(); Object lock2 = new Object(); Thread t1 = new Thread(()->{ System.out.println("線程1開(kāi)始執(zhí)行"); synchronized (lock1){ try { lock1.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程1執(zhí)行完成"); } },"無(wú)參wait線程"); t1.start(); Thread t2 = new Thread(()->{ System.out.println("線程2開(kāi)始執(zhí)行"); synchronized (lock2){ try { lock2.wait(60*60*1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程2執(zhí)行完成"); } },"有參wait線程"); t2.start(); } }
wait結(jié)束等待的條件
①其他線程調(diào)用該對(duì)象的 notify 方法.
②wait 等待時(shí)間超時(shí) (wait 方法提供一個(gè)帶有 timeout 參數(shù)的版本, 來(lái)指定等待時(shí)間).
③其他線程調(diào)用該等待線程的 interrupted 方法, 導(dǎo)致 wait 拋出 InterruptedException 異常
三、notify和notifyAll方法
notify 方法只是喚醒某一個(gè)等待的線程
- 方法notify()也要在同步方法或同步塊中調(diào)用,該方法是用來(lái)通知那些可能等待該對(duì)象的對(duì)象鎖的其它線程
- 如果有多個(gè)線程等待,隨機(jī)挑選一個(gè)wait狀態(tài)的線程
- 在notify()方法后,當(dāng)前線程不會(huì)馬上釋放該對(duì)象鎖,要等到執(zhí)行notify()方法的線程將程序執(zhí)行完,也就是退出同步代碼塊之后才會(huì)釋放對(duì)象鎖
notify方法的使用
/** * wait的使用, 如果有多個(gè)線程等待,隨機(jī)挑選一個(gè)wait狀態(tài)的線程 */ public class WaitNotifyDemo { public static void main(String[] args) { Object lock1 = new Object(); Object lock2 = new Object(); Thread t1 = new Thread(()->{ System.out.println("線程1開(kāi)始執(zhí)行"); try { synchronized (lock1) { System.out.println("線程1調(diào)用wait方法"); lock1.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程1執(zhí)行完成"); },"線程1"); Thread t2 = new Thread(()->{ System.out.println("線程2開(kāi)始執(zhí)行"); try { synchronized (lock1) { System.out.println("線程2調(diào)用wait方法"); lock1.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程2執(zhí)行完成"); },"線程2"); t1.start(); t2.start(); // 喚醒 lock1 對(duì)象上休眠的線程的(隨機(jī)喚醒一個(gè)) Thread t3 = new Thread(()->{ try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程3開(kāi)始執(zhí)行"); synchronized (lock1){ //發(fā)出喚醒通知 System.out.println("執(zhí)行了喚醒"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } },"線程3"); t3.start(); } }
notifyAll方法可以一次喚醒所有的等待線程
notifyAll方法的使用
/** * notifyAll-喚醒所有線程 */ public class WaitNotifyAll { public static void main(String[] args) { Object lock = new Object(); new Thread(() -> { System.out.println("線程1:開(kāi)始執(zhí)行"); synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程1:執(zhí)行完成"); } }, "無(wú)參wait線程").start(); new Thread(() -> { synchronized (lock) { System.out.println("線程2:開(kāi)始執(zhí)行 |" + LocalDateTime.now()); try { lock.wait(60 * 60 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程2:執(zhí)行完成 | " + LocalDateTime.now()); } }, "有參wait線程").start(); new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock) { System.out.println("喚醒所有線程"); lock.notifyAll(); } }).start(); } }
notify和notifyAll方法的區(qū)別
- 當(dāng)你調(diào)用notify時(shí),只有一個(gè)等待線程會(huì)被喚醒而且它不能保證哪個(gè)線程會(huì)被喚醒,這取決于線程調(diào)度器。
- 調(diào)用notifyAll方法,那么等待該鎖的所有線程都會(huì)被喚醒,但是在執(zhí)行剩余的代碼之前,所有被喚醒的線程都將爭(zhēng)奪鎖定,這就是為什么在循環(huán)上調(diào)用wait,因?yàn)槿绻鄠€(gè)線程被喚醒,那么線程是將獲得鎖定將首先執(zhí)行,它可能會(huì)重置等待條件,這將迫使后續(xù)線程等待。
- 因此,notify和notifyAll之間的關(guān)鍵區(qū)別在于notify()只會(huì)喚醒一個(gè)線程,而notifyAll方法將喚醒所有線程。
到此這篇關(guān)于Java詳細(xì)分析sleep和wait方法有哪些區(qū)別的文章就介紹到這了,更多相關(guān)Java sleep與wait內(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面試突擊之sleep和wait有什么區(qū)別詳析
- Java中wait()與sleep()兩者的不同深入解析
相關(guān)文章
Spring中@PathVariable注解的簡(jiǎn)單使用
這篇文章主要介紹了Spring中@PathVariable注解的簡(jiǎn)單使用,@PathVariable 是 Spring Framework 中的注解之一,用于處理 RESTful Web 服務(wù)中的 URL 路徑參數(shù),它的作用是將 URL 中的路徑變量綁定到方法的參數(shù)上,需要的朋友可以參考下2024-01-01基于SpringBoot+Redis的Session共享與單點(diǎn)登錄詳解
這篇文章主要介紹了基于SpringBoot+Redis的Session共享與單點(diǎn)登錄,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07SpringBoot通過(guò)Nginx代理獲取真實(shí)IP
springboot作為后臺(tái)代碼,獲取到的登錄IP是前臺(tái)的代理服務(wù)器地址,并不是用戶的真實(shí)IP地址,本文主要介紹了SpringBoot通過(guò)Nginx代理獲取真實(shí)IP,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01MyBatis?實(shí)現(xiàn)多對(duì)多中間表插入數(shù)據(jù)
這篇文章主要介紹了MyBatis?實(shí)現(xiàn)多對(duì)多中間表插入數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02詳解SpringBoot中的統(tǒng)一結(jié)果返回與統(tǒng)一異常處理
這篇文章主要將通過(guò)詳細(xì)的討論和實(shí)例演示來(lái)幫助你更好地理解和應(yīng)用Spring Boot中的統(tǒng)一結(jié)果返回和統(tǒng)一異常處理,感興趣的小伙伴可以了解下2024-03-03SpingMvc復(fù)雜參數(shù)傳收總結(jié)
這篇文章主要為大家介紹了SpingMvc復(fù)雜參數(shù)傳收總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08spring cloud config 配置中心快速實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了spring cloud config 配置中心快速實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Spring Boot集成MyBatis訪問(wèn)數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了Spring Boot集成MyBatis訪問(wèn)數(shù)據(jù)庫(kù)的方法,需要的朋友可以參考下2017-04-04MyBatis-Plus 修改和添加自動(dòng)填充時(shí)間方式
這篇文章主要介紹了MyBatis-Plus 修改和添加自動(dòng)填充時(shí)間方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08