java多執行緒:結合多執行緒交替列印10次abc例項,對wait/notify使用的徹底理解
有個朋友看點選開啟連結 裡的三個執行緒“A執行緒列印10次A,B執行緒列印10次B,C執行緒列印10次C,要求執行緒同時執行,交替列印10次ABC。” 這個問題的程式碼,有點不太理解,讓我給看下。不理解的原因也很簡單,就是對wait和notify理解不深,遇到複雜點的場景會迷糊。對於併發相關的東西,非常推薦書併發程式設計實戰(童雲蘭譯)。這篇部落格純粹是為了直觀理解而寫,所以講解時用詞不準確,如果是想看一些概念的精確定義,建議看書,不要看這篇。
/** * wait用法 * @author DreamSea * @time 2015.3.9 */ package com.multithread.wait; public class MyThreadPrinter2 implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter2(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; while (count > 0) { synchronized (prev) { // 1 程式碼1 處 synchronized (self) { // 2 程式碼2 處 System.out.print(name); count--; self.notify(); // 3 程式碼3處 } try { prev.wait(); // 4 程式碼4處 } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); new Thread(pa).start(); Thread.sleep(100); //確保按順序A、B、C執行 new Thread(pb).start(); Thread.sleep(100); new Thread(pc).start(); Thread.sleep(100); } }
正文:
一些概念:
1 wait會釋放鎖,並使當前執行緒休眠。
2 有一點需要注意的是notify()呼叫後,並不是馬上就釋放物件鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖。
結合程式碼理解:
問1: "wait會釋放鎖,並使當前執行緒休眠"的理解
第一次A執行緒先執行,new Thread(pa).start()。在程式碼中1和2處分別擁有prev(c鎖)和self(a鎖)。
對於初學者來說在A執行緒過程中,程式碼中4處要理解到哪些點呢?
第一點,wait會釋放鎖,釋放誰的鎖?因為是prev.wait(),所以釋放的是prev鎖,即c鎖。第二點,使執行緒休眠,哪個執行緒休眠?
{2018.5.27補充:
最近想系統的看下併發程式設計相關的東西,更進一步的研究下邊邊角角的小知識。看併發程式設計實戰的時候,不知是中文翻譯的問題,還是圖書作者doug lea段位太高的原因,有些段落讓人讀了不明所以。於是就結合了其他併發書籍交叉閱讀。在翻"java併發程式設計的藝術"時,掃了一眼“等待/通知機制”章節,發現介紹的還不錯,而且也正好和我的這篇部落格主題契合,這裡就摘要一些。轉載自連結:
等待/通知的相關方法是任意Java物件都具備的,因為這些方法被定義在所有物件的超類java.lang.Object上。
等待/通知機制,是指一個執行緒A呼叫了物件O的wait()方法進入等待狀態,而另一個執行緒B呼叫了物件O的notify()或者notifyAll()方法,執行緒A收到通知後從物件O的wait()方法返回,進而執行後續操作。上述兩個執行緒通過物件O來完成互動,而物件上的wait()和notify/notifyAll()的關係就如同開關訊號一樣,用來完成等待方和通知方之間的互動工作。
}
問2: notify()呼叫後,會馬上就釋放物件鎖
下文中的程式碼3處,notify()呼叫後並不是馬上就釋放物件鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖。
問3:小結下A執行緒的執行流程
執行程式碼1和2處,分別是c和a鎖,這點很好理解。程式碼3處釋放a鎖。程式碼4處,釋放c鎖,同時休眠A執行緒,下次需要c.notify() 才能喚醒A執行緒。
有lock鎖,ReentrantLock結合Condition,訊號量Semaphore等。我部落格所有文章連結:http://blog.csdn.net/wabiaozia