线程之间等待通知的一种机制。类似于LockSupport,可以使一个线程等待,然后去唤醒另外一个线程。
Condition是一个接口,获取它的方式可以通过lock.newCondition()获取。
public static void main(String[] args){ReentrantLock lock = new ReentrantLock();Condition condition = lock.newCondition();}
- 线程间的通信
- 每个锁上可以存在多个condition,这意味着锁的状态条件可以有多个
- 支持公平和非公平的队列操作
- 支持可中断的条件等待
- 支持可定时的等待
源码分析
await()
使当前线程等待或中断,直到有其他线程唤醒。线程调用await方法会处于等待状态,此时调用Thread.interrupt()方法会报IllegalMonitorStateException异常awaitUninterruptibly()
线程调用awaitUninterruptibly方法会处于等待状态,此时调用Thread.interrupt()方法不会报错。awaitNanos(long nanosTimeout)
线程处于等待状态,设置等待时间为nanosTimeout。
返回值:nanosTimeout减去线程等待的时间,大于0表示还有时间,小于或等于0表示没有时间啦。await(long time,TimeUnit unit)
等待time时间或者中断awiatUntil(Date deadline)
等待直到deadlinesignal()
唤醒一个等待的线程signalAll()
唤醒所有的等待线程
使用场景
Condition作为等待通知的机制,在JUC包中的很多类中都使用到,比如ArrayBlockingQueue阻塞队列内部就维护了两个Condition(notEmpty,notFull)来实现生产者消费者模式,notEmpty作为取(take),notFull作为存(push)
生产者消费者模式
ArrayBlockingQueue的实现
public static void main(String[] args) throws InterruptedException {int queueCapacity = 10;PriorityQueue<Integer> queue = new PriorityQueue(queueCapacity);ReentrantLock lock = new ReentrantLock();Condition notEmpty = lock.newCondition();Condition notFull = lock.newCondition();Thread consumerThread = new Thread(() -> {boolean flag = true;while(flag) {lock.lock();try {while (queue.size() == 0) {System.out.println("队列为空,等待生产数据。。。");notEmpty.await();}queue.poll();notFull.signal();System.out.println("消费者从队列中消费一条数据,队列剩余数据: " +queue.size());} catch (Exception e) {flag = false;} finally {lock.unlock();}}}, "consumerThread");Thread producerThread = new Thread(() -> {boolean flag = true;while(flag){lock.lock();try {while (queue.size() == queueCapacity) {System.out.println("队列已满,等待消费。。。");notFull.await();}queue.offer(1);notEmpty.signal();System.out.println("生产者向队列中插入一条数据,队列剩余空间:" + (queueCapacity - queue.size()));} catch (Exception e) {flag = false;} finally {lock.unlock();}}}, "producerThread");producerThread.start();consumerThread.start();Thread.sleep(0);producerThread.interrupt();consumerThread.interrupt();}
循环打印
public static void main(String[] args){Lock lock = new ReentrantLock();Condition conditionT1 = lock.newCondition();Condition conditionT2 = lock.newCondition();char[] num = "1234567890".toCharArray();char[] word = "ABCDEFGHIJ".toCharArray();new Thread(() -> {lock.lock();try{for (char c : num) {System.out.print(c);conditionT2.signal();conditionT1.await();}conditionT2.signal();}catch(Exception e){}finally {lock.unlock();}},"t1").start();new Thread(() -> {lock.lock();try{for (char c : word) {System.out.print(c);conditionT1.signal();conditionT2.await();}conditionT1.signal();}catch(Exception e){}finally {lock.unlock();}},"t2").start();}
