Java wait notify解析

方法/ 作用

wait: 線程自動釋放佔有的對象鎖,並等待notify。
notify: 隨機喚醒一個正在wait當前對象的線程,並讓被喚醒的線程拿到對象鎖
notifyAll: 喚醒所有正在wait當前對象的線程,但是被喚醒的線程會再次去競爭對象鎖。因爲一次只有一個線程能拿到鎖,所有其他沒有拿到鎖的線程會被阻塞。推薦使用。

Java中規定,在調用這三個方法時,當前線程必須獲得對象鎖。因此就得配合synchronized關鍵字來使用。在synchronized拿到對象鎖之後,synchronized代碼塊或者方法中,必定是會持有對象鎖的,因此就可以使用wait()或者notify()。

使用wait()、notify()來實現一個生產者、消費者模式:
class ProductAndCusumer {
    private static final Integer MAX_CAPACITY = 5;
    private static LinkedList<String> queue = new LinkedList<>();  //需要將queue作爲多線程操作的鎖

    static class Producter extends Thread {
        @Override
        public void run() {
            while (true) {
                synchronized (queue) {

                    if (queue.size() >= MAX_CAPACITY * 2) {
                        System.out.println("緩衝隊列已滿");

                        //停止生產產品,此時在生產者的線程中,調用queue.wait主動去釋放鎖,
                        //讓當前消費線程進入等待喚醒去拿鎖
                        try {
                            queue.wait();
                        } catch (Exception e) {
                        }
                    }

                    //沒有滿,繼續生產
                    String product = "生產:" + Thread.currentThread().getName();
                    System.out.println(product);
                    queue.add(product);
                    try {
                        Thread.sleep(500);
                    } catch (Exception e) {

                    }

                    try {
                        queue.notifyAll();  //喚醒所有線程拿鎖
                    } catch (Exception e) {
                    }
                }

            }

        }
    }

    static class Consumer extends Thread {
        @Override
        public void run() {
            while (true) {
                synchronized (queue) {
                    if (queue.isEmpty()) {
                        System.out.println("緩衝隊列爲空,暫無消費產品");
                        try {
                            queue.wait();
                        } catch (Exception e) {
                        }
                    }

                    try {
                        System.out.println("消費:" + queue.pop());
                        Thread.sleep(500);
                        queue.notifyAll();
                    } catch (Exception e) {
                    }

                }

            }
        }
    }

    public static void main(String[] args) {
        new Producter().start();
        new Consumer().start();
    }

}

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