wait notify
幾個注意點:
wait 與 notify/notifyAll 方法必須在同步代碼塊中使用,即要先對調用對象加鎖。
當線程執行wait()時,會把當前的鎖釋放,然后讓出CPU,進入等待狀態。
當執行notify/notifyAll方法時,會喚醒一個處于等待該 對象鎖 的線程,然后繼續往下執行,直到執行完退出對象鎖鎖住的區域(synchronized修飾的代碼塊)后再釋放鎖。
從這里可以看出,notify/notifyAll()執行后,并不立即釋放鎖,而是要等到執行完臨界區中代碼后,再釋放。故,在實際編程中,我們應該盡量在線程調用notify/notifyAll()后,立即退出臨界區。即不要在notify/notifyAll()后面再寫一些耗時的代碼
示例代碼:
public class Service { public void testMethod(Object lock) { try { synchronized (lock) { System.out.println("begin wait() ThreadName=" + Thread.currentThread().getName()); lock.wait(); System.out.println(" end wait() ThreadName=" + Thread.currentThread().getName()); } } catch (InterruptedException e) { e.printStackTrace(); } } public void synNotifyMethod(Object lock) { try { synchronized (lock) { System.out.println("begin notify() ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); lock.notify(); Thread.sleep(5000); System.out.println(" end notify() ThreadName=" + Thread.currentThread().getName() + " time=" + System.currentTimeMillis()); } } catch (InterruptedException e) { e.printStackTrace(); } } }
在第3行的testMethod()中調用 wait(),在第17行的synNotifyMethod()中調用notify()
從上面的代碼可以看出,wait() 與 notify/notifyAll()都是放在同步代碼塊中才能夠執行的。如果在執行wait() 與 notify/notifyAll() 之前沒有獲得相應的對象鎖,就會拋出:java.lang.IllegalMonitorStateException異常。
在第8行,當ThreadA線程執行lock.wait();這條語句時,釋放獲得的對象鎖lock,并放棄CPU,進入等待隊列。
當另一個線程執行第23行lock.notify();,會喚醒ThreadA,但是此時它并不立即釋放鎖,接下來它睡眠了5秒鐘(sleep()是不釋放鎖的,事實上sleep()也可以不在同步代碼塊中調用),直到第28行,退出synchronized修飾的臨界區時,才會把鎖釋放。這時,ThreadA就有機會獲得另一個線程釋放的鎖,并從等待的地方起(第24行)起開始執行。
notify 通知的順序不能錯
假設在線程A中執行wait(),在線程B中執行notify()。但如果線程B先執行了notify()然后結束了,線程A才去執行wait(),那此時,線程A將無法被正常喚醒了(還可以通過interrupt()方法以拋出異常的方式喚醒^~^)。
join
thread.Join把指定的線程加入到當前線程,可以將兩個交替執行的線程合并為順序執行的線程。比如在線程B中調用了線程A的Join()方法,直到線程A執行完畢后,才會繼續執行線程B。
如果一個線程A執行了thread.join()語句,含義是:當前線程A等待thread線程終止之后也從thread.join()返回
thread.join還可以指定超時時間
文章列表