詳細分析java線程wait和notify
wait()和notify()是直接隸屬于Object類,也就是說,所有對象都擁有這一對方法。初看起來這十分 不可思議,但是實際上卻是很自然的,因為這一對方法阻塞時要釋放占用的鎖,而鎖是任何對象都具有的,調用任意對象的 wait() 方法導致線程阻塞,并且該對象上的鎖被釋放。而調用任意對象的notify()方法則導致因調用該對象的wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。
其次,wait()和notify()可在任何位置調用,但是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在 synchronized 方法或塊中當前線程才占有鎖,才有鎖可以釋放。同樣的道理,調用這一對方法的對象上的鎖必須為當前線程所擁有,這樣才有鎖可以 釋放。因此,方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的加鎖對象就是調用這些方法的對象。若不滿足這一條 件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。
wait() 和 notify() 方法的上述特性決定了它們經常和synchronized 方法或塊一起使用,將它們和操作系統的進程間通信機制作 一個比較就會發(fā)現它們的相似性:synchronized方法或塊提供了類似于操作系統原語的功能,它們的執(zhí)行不會受到多線程機制的干擾,而這一對方法則 相當于 block 和wakeup 原語(這一對方法均聲明為 synchronized)。它們的結合使得我們可以實現操作系統上一系列精妙的進程間 通信的算法(如信號量算法),并用于解決各種復雜的線程間通信問題。
關于 wait() 和 notify() 方法最后再說明兩點:
第一:調用 notify() 方法導致解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,我們無法預料哪一個線程將會被選擇,所以編程時要特別小心,避免因這種不確定性而產生問題。
第二:除了 notify(),還有一個方法 notifyAll() 也可起到類似作用,唯一的區(qū)別在于,調用 notifyAll() 方法將把因調 用該對象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當然,只有獲得鎖的那一個線程才能進入可執(zhí)行狀態(tài)。
相關wait和notify使用demo:
/** * <pre> * 子線程循環(huán)10次,接著主線程循環(huán)100次,接著有回到子線程循環(huán)10次, * 接著再回到主線程循環(huán)100次,如此執(zhí)行50次 * </pre> * @author ketqi */ public class WaitNotifyDemo { public static void main(String[] args) { final Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { business.main(i); } } } class Business { private boolean isMainThread = true; public synchronized void sub(int i) { while (!isMainThread) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("sub thread sequence of " + j + ",loop of " + i); } isMainThread = false; this.notify(); } public synchronized void main(int i) { while (isMainThread) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 100; j++) { System.out.println("main thread sequence of " + j + ",loop of " + i); } isMainThread = true; this.notify(); } }
以上就是本文的全部內容,希望大家可以喜歡。
相關文章
SpringMVC 重新定向redirect請求中攜帶數據方式
這篇文章主要介紹了SpringMVC 重新定向redirect請求中攜帶數據方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Java使用ByteArrayOutputStream 和 ByteArrayInputStream 避免重復讀取配置文
這篇文章主要介紹了Java使用ByteArrayOutputStream 和 ByteArrayInputStream 避免重復讀取配置文件的方法,需要的朋友可以參考下2015-12-12mybatis mybatis-plus-generator+clickhouse自動生成代碼案例詳解
這篇文章主要介紹了mybatis mybatis-plus-generator+clickhouse自動生成代碼案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08