Java并發(fā)之wait、notify、notifyAll詳解

線程狀態(tài)轉(zhuǎn)換圖.png

問題:請使用兩個線程一個線程用來打印1-26,另一個線程依次打印A-Z,要求交叉打印。

//1.使用wait和notify方法
public class WaitAndNotify {
    static Thread t1=null,t2=null;
    private static volatile boolean t1HasPrint=false;//標(biāo)記信號量
    public static void main(String[] args) {
        Object lock=new Object();

        t1=new Thread(()->{
            for (char i='A';i<='Z';i++){
                synchronized (lock){
                    while (t1HasPrint){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.print(i);
                    t1HasPrint=true;
                    lock.notify();

                }
            }
        },"t1");

        t2=new Thread(()->{
            for (int i=1;i<=26;i++){
                synchronized (lock){
                    while (!t1HasPrint){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(i);
                    t1HasPrint=false;
                    lock.notify();
                }
            }
        },"t2");

        t2.start();
        t1.start();
    }
}

//2.使用LockSupport
public class TestLockSupport {
    static Thread t1=null,t2=null;
    private static volatile boolean t1HasPrint=false;
    public static void main(String[] args) {

        t1=new Thread(()->{
            for (char i='A';i<='Z';i++){
                    while (t1HasPrint){
                        LockSupport.park();
                    }
                    System.out.print(i);
                    t1HasPrint=true;
                    LockSupport.unpark(t2);

            }
        },"t1");

        t2=new Thread(()->{
            for (int i=1;i<=26;i++){
                while (!t1HasPrint){
                    LockSupport.park();
                }
                System.out.print(i);
                t1HasPrint=false;
                LockSupport.unpark(t1);
            }
        },"t2");

        t2.start();
        t1.start();
    }
}

總結(jié)

  1. wait()、notify/notifyAll() 方法是Object的本地final方法,無法被重寫。
  2. 一般在synchronized同步代碼塊里使用wait()、notify()和notifyAll()方法。
  3. 當(dāng)線程執(zhí)行wait()方法時(shí),會釋放當(dāng)前的鎖,然后讓出CPU,進(jìn)入等待隊(duì)列。(所以使用wait()的前提的先獲得鎖)
  4. 當(dāng)線程t執(zhí)行notify或notifyAll()方法后,會喚醒一個或全部正處于等待狀態(tài)的線程,但是線程t不會立即釋放鎖,直到執(zhí)行完同步代碼塊的代碼或者遇到wait()方法,才會釋放鎖。所以被喚醒的鎖也不會立即獲得鎖。
  5. wait() 需要被try catch包圍,以便發(fā)生異常中斷也可以使wait等待的線程喚醒。
  6. notify喚醒沉睡的線程后,線程會接著上次的執(zhí)行繼續(xù)往下執(zhí)行。
  7. 永遠(yuǎn)在循環(huán)里調(diào)用wait()和notify(),而不是在if語句。
  8. notify方法只喚醒一個等待線程。notifyAll 會喚醒所有等待線程,盡管哪一個線程將會第一個處理取決于操作系統(tǒng)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容