Java—多線程6 生產和消費者模型1

Java—多線程6 生產和消費者模型

生產者消費者模型

生產者和消費者不直接通信 而是通過一個阻塞隊列通信

wait()方法

使得當前線程立刻停止運行,處於等待狀態,並將當前狀態置入鎖對象的等待隊列中,直到被通知(notify())或中斷爲止。

使用條件:只能在同步方法或者同步代碼塊中使用,必須是內建鎖。

wait()調用後立刻釋放對象鎖。

1.一直等,直到被喚醒或者中斷。

public final void wait() throws InterruptedException {
    wait(0);
}

2.超時等待。若在規定時間內未被喚醒,則線程退出

public final native void wait(long timeout) throws InterruptedException;

3.在2的基礎上進行納秒級別的參數傳入

public final void wait(long timeout, int nanos) throws InterruptedException

notify()

喚醒處於等待中的線程

使用條件:notify必須在同步方法或者同步代碼塊中調用,用來喚醒等待該對象的其他線程,如果有多個線程在等待,隨機挑選一個喚醒(但是具體喚醒哪一個是版本決定的,JDK8 默認是等待隊列的第一個)

public final native void notify();

notify方法調用後不會立刻釋放對象鎖,要等到當前線程執行完後釋放對象鎖。

wait和 notify必須操作的是統一個對象

class MyThread implements Runnable{
    private boolean flag;
    private Object obj;

    public MyThread(boolean flag, Object obj) {
        this.flag = flag;
        this.obj = obj;
    }

    public void waitMethod() throws InterruptedException {
        synchronized (obj){
            System.out.println(Thread.currentThread().getName()+"開始");
            obj.wait();
            System.out.println(Thread.currentThread().getName()+"結束");
        }
    }
    public void notifyMethod(){
        synchronized (obj){
            System.out.println(Thread.currentThread().getName()+"開始");
            obj.notify();
            System.out.println(Thread.currentThread().getName()+"結束");
        }
    }

    @Override
    public void run() {
        if(flag){
            try {
                waitMethod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            notifyMethod();
        }
    }
}

public class Test{
    public static void main(String[] args) throws InterruptedException {
        Object obj=new Object();
        MyThread mt1=new MyThread(true,obj);
        MyThread mt2=new MyThread(false,obj);
        new Thread(mt1,"wait").start();
        Thread.sleep(1000);
        new Thread(mt2,"notify").start();
    }
}

運行結果:

wait開始
notify開始
notify結束
wait結束

可以看出,wait不喚醒會一直等下去,但是notify()調用後不會立刻釋放對象鎖,而是要到當前線程執行完才叫鎖。

線程由運行態到阻塞態

1.調用sleep,立刻交出CPU,不釋放鎖

2.線程調用阻塞時IO(BIO)方法

3.線程獲取鎖失敗進入阻塞狀態

4,線程調用wait()

5.線程調用suspend(),將線程掛起

每個鎖對象都有兩個隊列。

1.同步隊列,存儲獲取鎖失敗的線程。

2.另一個稱爲等待隊列存儲調用wait()等待線程。

將線程喚醒實際上是將等待隊列的線程移到同步隊列中競爭鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章