1. 程式人生 > >消費者與生產者模型--wait( )和notify( )方法

消費者與生產者模型--wait( )和notify( )方法

生產者與消費者

wait()方法

  1. 方法wait()的作用是使當前執行程式碼的執行緒進行等待,wait()方法是Object類的方法,該方法是用來將當前執行緒置入“預執行佇列”中,並且在wait()所在的程式碼處停止執行,直到接到通知或被中斷為止。
  2. wait()方法只能在同步方法中或同步塊中呼叫。如果呼叫wait()時,沒有持有適當的鎖,會丟擲異常
  3. wait()方法執行後,當前執行緒釋放鎖,執行緒與其它執行緒競爭重新獲取鎖。

notify()方法

  1. 方法notify()也要在同步方法或同步塊中呼叫,該方法是用來通知那些可能等待該物件的物件鎖的其它執行緒,對其發出通知notify,並使它們重新獲取該物件的物件鎖。如果有多個執行緒等待,則有執行緒規劃器隨機挑選出一個呈wait狀態的執行緒。

  2. 在notify()方法後,當前執行緒不會馬上釋放該物件鎖,要等到執行notify()方法的執行緒將程式執行完,也就是退出同步程式碼塊之後才會釋放物件鎖

class MyThread implements Runnable{
    //
    private Object object;
    private boolean flag;

    public MyThread(Object object,boolean flag){
        this.object = object;
        this.flag = flag;
    }
    public void waitMethod(){
        synchronized (object){
            System.out.println("wait方法開始。。"+Thread.currentThread().getName());
            try{
                object.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("wait方法結束。。"+Thread.currentThread().getName());

        }
    }
    public void notifyMethod(){
        synchronized (object){
            System.out.println("notify方法開始。。"+Thread.currentThread().getName());

                object.notifyAll();

            System.out.println("notify方法結束。。"+Thread.currentThread().getName());

        }
    }
    public void run(){

        if(flag){
            this.waitMethod();
        }else{
            this.notifyMethod();
        }
    }
}
class Test{
    public static void main(String[] args) {
        Object object = new Object();
       MyThread mythread = new MyThread(object,true);
       for(int i =0;i<10;i++){
           Thread thread1 = new Thread(mythread,"wait執行緒"+i);
           thread1.start();
       }

       MyThread mythread2 = new MyThread(object,false);
       Thread thread3 = new Thread(mythread2);
       thread3.start();
    }
}


從結果上來看第一個執行緒執行的是一個waitMethod方法,該方法裡面有個死迴圈並且使用了wait方法進入等待狀態
將釋放鎖,如果這個執行緒不被喚醒的話將會一直等待下去,這個時候第二個執行緒執行的是notifyMethod方法,該方
法裡面執行了一個喚醒執行緒的操作,並且一直將notify的同步程式碼塊執行完畢之後才會釋放鎖然後繼續執行wait結束
列印語句

notifyAll()方法

  • 使用notifyAll()方法喚醒所有等待執行緒
class MyThread implements Runnable{

    private Object object;
    private boolean flag;

    public MyThread(Object object,boolean flag){
        this.object = object;
        this.flag = flag;
    }
    public void waitMethod(){
        synchronized (object){
            System.out.println("wait方法開始。。"+Thread.currentThread().getName());
            try{
                object.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("wait方法結束。。"+Thread.currentThread().getName());

        }
    }
    public void notifyMethod(){
        synchronized (object){
            System.out.println("notify方法開始。。"+Thread.currentThread().getName());

                object.notifyAll();

            System.out.println("notify方法結束。。"+Thread.currentThread().getName());

        }
    }
    public void run(){

        if(flag){
            this.waitMethod();
        }else{
            this.notifyMethod();
        }
    }
}
class Test{
    public static void main(String[] args) {
        Object object = new Object();
       MyThread mythread = new MyThread(object,true);
       for(int i =0;i<10;i++){
           Thread thread1 = new Thread(mythread,"wait執行緒"+i);
           thread1.start();
       }

       MyThread mythread2 = new MyThread(object,false);
       Thread thread3 = new Thread(mythread2);
       thread3.start();

    }
}

生產者與消費者模型

  • 生產者與消費者開頭已經介紹過了,生產者與消費者一般需要第三者來解耦的,所以現在就模擬一個簡單的商品的生產者與消費者,由生產者執行緒生產出一個商品之後將由消費者執行緒開始消費
//商品類
class Goods{
    private String goodName;
    private  int count;
//生產商品方法
    public synchronized void set(String goodName){
        //while
        if(count > 0){
            System.out.println("商品還有吶");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodName = goodName;
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生產"+goodName+toString());
        //喚醒等待消費的庫存
        notify();
        //notifyAll();
    }
    //消費商品方法
    public synchronized void get(){
        //while
        if(count == 0){
            System.out.println("賣完啦~");
            try {
                //等待商品生產
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消費"+goodName+toString());
        //喚醒生產者生產
        notify();
        //notifyAll();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goodName='" + goodName + '\'' +
                ", count=" + count +
                '}';
    }
}
//生產執行緒
class Producer implements Runnable{
    private Goods goods;
    public Producer(Goods goods){
        this.goods = goods;
    }
    public void run(){
        //while(true){
            goods.set("牛排");
        //}

    }
}
//消費執行緒
class Consumer implements Runnable{
    private Goods goods;
    public Consumer(Goods goods){
        this.goods = goods;
    }
    public void run(){
        //while(true){
            goods.get();
        //}

    }
}
class Test{
    public static void main(String[] args) {
        Goods good = new Goods();//同一個物件
        Thread mythread = new Thread(new Producer(good),"生產者");
        Thread mythread1 = new Thread(new Consumer(good),"消費者");
        mythread.start();
        mythread1.start();
//        List<Thread> list = new ArrayList<>();
//        for (int i = 0;i<10;i++){
//            Thread thread new Thread(new Consumer(good),"xiaofeiz"+i);
//        }
    }
}