java多執行緒wait notify join

Gyoung發表於2016-12-04

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還可以指定超時時間

相關文章