1. 程式人生 > >談談wait()和notify()方法的使用

談談wait()和notify()方法的使用

 


1、對於wait()和notify()的理解:

wait()和notify()是Object類的方法,看一下jdk官方文件給出的資料

wait():

導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量。

當前的執行緒必須擁有此物件監視器。

notify():

喚醒在此物件監視器上等待的單個執行緒。如果所有執行緒都在此物件上等待,則會選擇喚醒其中一個執行緒。選擇是任意性的,並在對實現做出決定時發生。執行緒通過呼叫其中一個 wait 方法,在物件的監視器上等待。

直到當前的執行緒放棄此物件上的鎖定,才能繼續執行被喚醒的執行緒。被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭;

直白點說:wait()就是暫停當前正在執行的執行緒,並釋放資源鎖,讓其他執行緒可以有機會執行(程式停頓在這一行).

              :notify()就是通知等待佇列中的某一個執行緒;

2、使用用例:生產消費者

import java.util.ArrayList;
import java.util.List;

public class ThreadDemo {
    public static void main(String[] args) {
        Pool pool = new Pool();
        Productor p1 = new Productor("生產者", pool);
        Productor p2 = new Productor("生產者", pool);
        Customer c1 = new Customer("消費者", pool);
        p1.start();
        p2.start();
        c1.start();
    }
}

//生產者
class Productor extends Thread {
    static int i = 0;
    private String name;
    private Pool pool;

    public Productor(String name, Pool pool) {
        this.name = name;
        this.pool = pool;
    }

    public void run() {
        while (true) {
            pool.add(i++);
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("生產了" + i + "");
        }

    }
}

//消費者
class Customer extends Thread {
    private String name;
    private Pool pool;

    public Customer(String name, Pool pool) {
        this.name = name;
        this.pool = pool;
    }

    public void run() {
        while (true) {
            int i = pool.remove();
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("消費了" + i);
        }
    }
}


//生產 刪除方法類
class Pool {
    private List<Integer> list = new ArrayList<Integer>();
    //容量最大值
    private int Max = 100;//防止棧溢位,到達100等待

    //新增元素
    public void add(int n) {
        synchronized (this) {
            try {
                while (list.size() >= Max) {
                    this.wait();
                }
                list.add(n);
                System.out.println("size ==" + list.size());
                this.notify();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //刪除元素
    public int remove() {
        synchronized (this) {
            try {
                while (list.size() == 0) {
                    this.wait();
                }
                int i = list.remove(0);
                this.notify();
                return i;

            } catch (Exception e) {
                e.printStackTrace();
            }
            return -1;
        }
    }

}

3、需要特殊注意的地方    

  • 當需要呼叫wait()和notify()方法時,一定要對競爭資源進行加鎖,如果不加鎖會報java.lang.IllegalMonitorStateException 異常;
  • 消費者被喚醒後是從wait()方法後面執行,而不是重新從同步塊開始;

 

 

                                                                                                               翻過那座山,世界會看到你  --------作者:劉村長