4.3 使用lock的condition實現等待/通知機制

Condition接口

任意一個Java對象,都擁有一組監視器方法(定義在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,這些方法與synchronized同步關鍵字配合,可以實現等待/通知模式。Condition接口也提供了類似Object的監視器方法,與Lock配合可以實現等待/通知模式。

Condition常用方法

方法名稱 描述
void await() throws InterruptedException

當前線程進入等待,知道被condition.signal()喚醒或者被中斷

void awaitUninterruptibly()  當前線程進入等待,能夠響應中斷

long awaitNanos(long nanosTimeout) thrwos

InterruptedException

1、返回0或者負數,表示超時了

2、正常被喚醒,返回剩餘時間

boolean awaitUnitil(Date deadline) throws

InterruptedException

1、如果沒有到指定時間就返回通知,返回true

2、倒了指定時間還沒有被通知,返回false

void signal() 喚醒一個在condition.await()的程序
void signal()  喚醒所有等待在condition上的現成

Condition使用格式

// 等待
lock.lock();
try {
	condition.await();
} finally {
	lock.unlock();
}

// 喚醒
lock.lock();
try {
	condition.signalAll();
} finally {
	lock.unlock();
}

 

備註:我一開始把condition.await();寫成了condition.wait();,結果每次執行到這裏的時候就會報錯,以爲是自己鎖用錯了,搞了半天才發現是少了個a,應該是await(),頓時心都碎了,特此記錄,防止有人採坑

具體報錯如下:

Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
消費者消費了一個麪包:9
消費者消費了一個麪包:8
消費者消費了一個麪包:7
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
消費者消費了一個麪包:6
	at cn.enjoyedu.ch4.TestCondition.product(TestCondition.java:24)
	at cn.enjoyedu.ch4.TestCondition.lambda$main$1(TestCondition.java:61)
	at java.lang.Thread.run(Thread.java:748)

示例:消費者生產者機制

public class TestCondition {
    private int count = 0;
    private static final int SUM = 10;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void product() {
        while (true) {
            lock.lock();
            try {
                while (count >= SUM) {
                    System.out.println("庫存滿了,等待消費" + count);
                    condition.await();
                }
                count++;
                System.out.println("生產者生產了一個麪包:" + count);
                condition.signalAll();
            } catch (InterruptedException e) {
                //e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public void customer() {
        while (true) {
            lock.lock();
            try {
                while (count <= 0) {
                    System.out.println("庫存爲零,等待生產:" + count);
                    condition.await();
                }
                count--;
                System.out.println("消費者消費了一個麪包:" + count);
                condition.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args){
        TestCondition testCondition = new TestCondition();
        for (int i = 0; i < 3; i++) {
            new Thread(() -> testCondition.customer()).start();

            new Thread(() -> testCondition.product()).start();
        }
    }
}

結果:

庫存爲零,等待生產:0
庫存爲零,等待生產:0
庫存爲零,等待生產:0
生產者生產了一個麪包:1
生產者生產了一個麪包:2
生產者生產了一個麪包:3
生產者生產了一個麪包:4
生產者生產了一個麪包:5
生產者生產了一個麪包:6
生產者生產了一個麪包:7
生產者生產了一個麪包:8
生產者生產了一個麪包:9
生產者生產了一個麪包:10
庫存滿了,等待消費10
庫存滿了,等待消費10
庫存滿了,等待消費10
消費者消費了一個麪包:9
消費者消費了一個麪包:8

 

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