《Java並發編程的藝術》讀書筆記:等待/通知機制
阿新 • • 發佈:2017-08-05
package tex 藝術 pri new [] 返回 ati block
輸出結果為:
通過輸出結果,我們能夠發現幾個問題。
看這本書之前,對wait和notify認識大概就是,調用wait的線程A堵塞之後,一旦另外有線程調用notify方法。線程A會立馬從wait方法處返回。看完這本書後。發現自己的認識實在太膚淺了。。。。。
。
線程調用wait()後,會釋放已經獲得的鎖。
同一時候進入Waiting狀態,而非Blocked狀態。唯獨等待其它的線程調用notify()方法且釋放鎖之後。當前線程才會從wait()方法處返回。只發出通知是不夠用的。還須要發出通知的線程釋放鎖。
然而notify()方法的調用並不意味著鎖的釋放。
貼出原書的demo,稍作了些改動。
/** * */ package chapter04; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; /** * 6-11 */ public class WaitNotify { private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); static boolean flag = true; static Object lock = new Object(); public static void main(String[] args) { Thread waitThread = new Thread(new Wait(), "WaitThread"); waitThread.start(); sleepSeconds(1); Thread notifyThread = new Thread(new Notify(), "NotifyThread"); notifyThread.start(); } static class Wait implements Runnable { public void run() { synchronized (lock) { // 當條件不滿足時,繼續wait,同一時候釋放了lock的鎖 while (flag) { try { System.out.println(CuttentThreadName() + " flag is true. wait @ " + sdf.format(new Date())); lock.wait(); System.out.println(CuttentThreadName() + " gained lock again. wait @ " + sdf.format(new Date())); } catch (InterruptedException e) { e.printStackTrace(); } } // 條件滿足時。完畢工作 System.out.println(CuttentThreadName() + " flag is false. running @ " + sdf.format(new Date())); } } } private static String CuttentThreadName() { return Thread.currentThread().getName(); } static class Notify implements Runnable { @Override public void run() { // 加鎖,擁有lock的Monitor synchronized (lock) { // 獲取lock的鎖。然後進行通知,通知時不會釋放lock的鎖, // 直到當前線程釋放了lock後,WaitThread才幹從wait方法中返回 System.out.println(CuttentThreadName() + " hold lock. notify @ " + sdf.format(new Date())); lock.notifyAll(); flag = false; sleepSeconds(5); System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date())); } // 再次加鎖 synchronized (lock) { System.out.println(CuttentThreadName() + " hold lock again. sleep @ " + sdf.format(new Date())); sleepSeconds(5); System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date())); } } } private static void sleepSeconds(int timeout) { try { TimeUnit.SECONDS.sleep(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } }
輸出結果為:
WaitThread flag is true. wait @ 20:58:32 NotifyThread hold lock. notify @ 20:58:33 NotifyThread is releasing lock @ 20:58:38 NotifyThread hold lock again. sleep @ 20:58:38 NotifyThread is releasing lock @ 20:58:43 WaitThread gained lock again. wait @ 20:58:43 WaitThread flag is false. running @ 20:58:43
通過輸出結果,我們能夠發現幾個問題。
1.NotifyThread調用notifyAll()方法後,WaitThread並沒有立馬從wait()方法處返回。
由於這個時候NotifyThread並沒有釋放鎖。
2.程序61行,NotifyThread第一次釋放鎖,然而WaitThread不爭氣,並沒有搶到這把鎖。依然處於Blocked狀態。
3.直到67行。NotifyThread再一次釋放鎖。WaitThread獲得了鎖,這才從wait()處返回繼續運行。
4.線程從wait()方法返回的前提是,獲得synchronized須要的鎖。
分析完原書的demo之後,是否有跟我一樣的感覺,以前的認識是那麽的too young too simple。
《Java並發編程的藝術》讀書筆記:等待/通知機制