天天看點

wait、notify和countDownLatch進行線程間互動

1.wait和notify

wait會釋放鎖,notify不會釋放鎖。wait和notify隻能在加鎖的情況下使用。

wait底層是引用的native方法,wait一定的時間。

notify喚醒一個對象,底層是一個native方法,隻能被該對象的monitor調用。

某個線程調用對象的wait方法,該線程進入等待模式且釋放鎖。其他線程可以通路。wait可以取消while循環的等待模式,減少CPU的消耗。

其他線程當調用對象的notify方法時,notify會啟動正在等待該對象的一個線程,但是由于notify不會釋放鎖,是以被喚醒的線程也隻能在本線程結束後才能執行。

而且,notify喚醒的線程是由CPU線程排程器自動配置設定的。

是以如果想讓notify喚醒的鎖不用等待本線程的結束,需要本線程調用wait自動釋放鎖,然後notify喚醒的線程執行結束之前,需要喚醒剛才wait的線程。

能使用countdownlatch就不要用wait,notify

比wait和notify更好的方式,是用CountDownLatch(門闩)

舉個例子

//對于一個簡單的不涉及同步的程序,能用CountDownLatch就不要用sybchronized+wait+notify的方法。
volatile List list=new ArrayList();
CountDownLatch latch=new CountDownLatch(1);//初始值,減到0之後,門闩打開,線程得以運作
new Thread(()->{
    if(list.size()!=5){
        try{
            latch.await();
        //用門闩等待的時候不需要鎖定任何對象,await之後,線程在此停住。
        }catch(InterruptedException e){
            e.printStackTrace;
        } 
    }
}).start();

new Thread(()->{
    for(int i=0;i<10;i++){
        list.add(new Object());
        System.out.println("add"+i);
        if(list.size()==5){
            try{
                latch.countDown();//每一次countDown(),初始值-1
                //打開門闩,剛才的線程得以繼續運作
            }catch(InterruptedException e){
                e.printStackTrace;
            }
        }
    }
}).start();