一、Condition接口简介
java.util.concurrent.locks.Condition是java并发包中的一个接口,是为配合Lock提供的线程等待/通知功能。我们知道Object的监视器方法wait()和notify()配合sychronized关键字一样可以实现等待/通知机制,Condition的优势在于它可以为多个线程间建立不同的Condition,控制粒度更细。如阻塞队列同时有读写线程,该唤醒读线程还是写线程,notify方法无法直接指定,而Condition可以做到。
Conditon的所有方法:
public interface Condition {
/**
* 线程进入等待状态,可被中断
* @throws InterruptedException
*/
void await() throws InterruptedException;
/**
* 线程进入等待状态,不可被中断
*/
void awaitUninterruptibly();
/**
* 线程进入等待状态,直到被中断、到达指定时间或唤醒
* @param nanosTimeout
* @return
* @throws InterruptedException
*/
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 线程进入等待状态,直到被中断、到达指定时间或唤醒
* @param time
* @param unit
* @return
* @throws InterruptedException
*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 线程进入等待状态,直到被中断、到达指定时间或唤醒
* @param deadline
* @return
* @throws InterruptedException
*/
boolean awaitUntil(Date deadline) throws InterruptedException;
/**
* 唤醒一个等待线程
*/
void signal();
/**
* 唤醒所有等待线程
*/
void signalAll();
}
二、Condition接口应用
典型应用就是LinkedBlockingQueue的实现,通过两个Condition分别控制读写线程的等待与通知,这里特别强调下,调用await方法和signal方法之前,该线程必须先获得锁,源代码如下:
public class LinkedBlockingQueue {
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
public void put(E e) throws InterruptedException {
// ...
final AtomicInteger count = this.count;
final ReentrantLock putLock = this.putLock;
// 必须先获得锁才能调用condition方法
putLock.lockInterruptibly();
try {
// 队列满时,通过notFull这个Conditon一直等待
while (count.get() == capacity) {
notFull.await();
}
// ...
} finally {
putLock.unlock();
}
// ...
}
public E take() throws InterruptedException {
// ...
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
// 必须先获得锁才能调用condition方法
takeLock.lockInterruptibly();
try {
// 队列空时,通过notEmpty这个condition一直等待
while (count.get() == 0) {
notEmpty.await();
}
// ...
} finally {
takeLock.unlock();
}
// ...
}
}
参考资料: