Condition
将 Object
监视器方法(wait、notify、notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用。
获取Condition实例:Lock接口中的newCondition()方法
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Condition中的实例方法:
- void await() 造成当前线程在接到信号或被中断之前一直处于等待状态
- void signal() 唤醒一个等待线程
- void signalAll() 唤醒所有等待线程
- boolean await(long time, TimeUnit unit) 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态
- long awaitNanos(long nanosTimeout) 当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态
- void awaitUninterruptibly() 当前线程在接到信号之前一直处于等待状态
- boolean awaitUntil(Date deadline) 当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态
Java API提供了如下Condition使用实例,用来实现阻塞队列:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
从上面的实例可以看出,Lock与Condition的组合,替代和扩展了synchronized与Object监视器方法的组合。且Condition中的await()、sgnal()、signalAll()方法与Object的监视器方法wait()、notify()、notifyAll()方法的使用方法基本相同。
Condition能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。如上面的示例中,同一个lock对象下创建了两个Condition——notFull 和 notEmpty,我们可以根据实际需要,指定唤醒特定的线程,而不需要向Object监视器方法的notify() 和 notifyAll()一样,随机唤醒或者全部唤醒。