等待(wait)和通知(notify)

爲了支持多線程之間的協作,jdk提供了兩個非常重要的方法線程等待wait()和通知notify()方法,這兩個方法不是Thread類的,而是屬於Object類。

方法的方法簽名:



當一個對象實例調用了wait()方法之後,當前線程就會在這個對象上等待。比如線程A中調用了obj.wait()方法,線程A就會停止繼續執行而轉爲等待狀態,等待狀態持續到其他線程調用了obj.notify()或obj.notifyAll()爲止。

當一個線程調用了obj.wait(),這個線程就會進入obj這個對象的等待隊列中。obj.notify()會在這個對象的等待隊列中隨機選擇一個線程進行通知喚醒;而notifyAll()則是通知喚醒等待線程隊列中所有的線程。

還有就是wait和notify都必須包含在對應的synchronized語句中,無論是wait()還是notify()都需要先獲取目標對象的一個監視器,並且執行之後都會釋放這個監視器,如下圖所示





wait()和notify()的例子:生產者消費者問題,代碼如下

package com.bckj.Thread;

/**
 * Created by Admin on 2017/6/12.
 */
//倉庫類
public class Store {
    private final int MAX_SIZE;  //倉庫的最大容量
    private int count;           //當前的倉庫數量
    public Store(int n){
        MAX_SIZE = n;
        count = 0;
    }
    //往倉庫加貨物的方法
    public synchronized void add(){       //使用了wait()或notify()方法,需要加上syncronized關鍵字
        while(count >= MAX_SIZE){          //否則可能會拋出java.lang.IllegalMonitorStateException
            System.out.println("已經滿了");
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        count++;
        //打印當前倉庫的貨物數量
        System.out.println(Thread.currentThread().toString()+" put"+count);
        //倉庫中已經有東西可以取了,則通知所有的消費者線程來拿
        this.notifyAll();
    }
    //從倉庫拿走貨物的方法
    public synchronized void remove(){
        while(count <= 0){
            System.out.println("空了");
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //打印當前倉庫的貨物數量
        System.out.println(Thread.currentThread().toString()+" get"+count);
        count--;
        //倉庫還沒裝滿,通知生產者添加貨物
        this.notify();
    }

    public static void main(String[] args) {
        Store s = new Store(5);         //創建容量爲5的倉庫
        //創建兩個生產者和兩個消費者
        Thread pro = new Producer(s);
        Thread con = new Consumer(s);
        Thread pro2 = new Producer(s);
        Thread con2 = new Consumer(s);
        pro.setName("producer");
        con.setName("consumer");
        pro2.setName("producer2");
        con2.setName("consumer2");
        //啓動各個線程
        pro.start();
        pro2.start();
        con.start();
        con2.start();
    }
}
class Producer extends Thread{          //生產者線程類
    private Store s;
    public Producer(Store s){
        this.s = s;
    }
    public void run(){      //線程方法
        while(true){        //永久循環
            s.add();        //往倉庫加貨物
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
class Consumer extends Thread{          //消費者線程類
    private Store s;
    public Consumer(Store s){
        this.s = s;
    }
    public void run(){      //線程方法
        while(true){        //永久循環
            s.remove();        //往倉庫取走貨物
            try{
                Thread.sleep(1500);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

執行結果:





發佈了27 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章