Condition 接口详解
JDK5 时提供。
- 条件队列 ConditionObject 实现了 Condition 接口
Condition 将对象监视方法(wait,notify和notifyAll)分解为不同的对象,从而通过与任意Lock实现结合使用,从而使每个对象具有多个wait-sets。 当 Lock 替换了 synchronized 方法和语句的使用,Condition 就可以替换了Object监视器方法的使用。
Condition 的实现可以提供与 Object 监视方法不同的行为和语义,例如保证通知的顺序,或者在执行通知时不需要保持锁定。 如果实现提供了这种专门的语义,则实现必须记录这些语义。
请注意,Condition实例只是普通对象,它们本身可以用作 synchronized 语句中的目标,并且可以调用自己的监视器 wait 和 notification 方法。 获取 Condition 实例的监视器锁或使用其监视器方法与获取与该条件相关联的锁或使用其 await 和 signal 方法没有特定的关系。 建议避免混淆,除非可能在自己的实现中,否则不要以这种方式使用 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();
}
}
}
(ArrayBlockingQueue类提供了此功能,因此没有理由实现此示例用法类。)
定义出一些方法,这些方法奠定了条件队列的基础
API
await
- 使当前线程等待,直到被 signalled 或被中断
与此 Condition 相关联的锁被原子释放,并且出于线程调度目的,当前线程被禁用,并且处于休眠状态,直到发生以下四种情况之一:
- 其它线程为此 Condition 调用了 signal 方法,并且当前线程恰好被选择为要唤醒的线程
- 其它线程为此 Condition 调用了 signalAll 方法
- 其它线程中断了当前线程,并且当前线程支持被中断
- 要么发生“虚假唤醒”。
在所有情况下,在此方法可以返回之前,必须重新获取与此 Condition 关联的锁,才能真正被唤醒。当线程返回时,可以保证保持此锁。
await 超时时间
- 使当前线程等待,直到被 signal 或中断,或经过指定的等待时间
此方法在行为上等效于:
awaitNanos(unit.toNanos(time)) > 0
所以,虽然入参可以是任意单位的时间,但其实仍会转化成纳秒
awaitNanos
注意这里选择纳秒是为了避免计算剩余等待时间时的截断误差
signal()
- 唤醒条件队列中的一个线程,在被唤醒前必须先获得锁
signalAll()
- 唤醒条件队列中的所有线程
- 点赞
- 收藏
- 关注作者
评论(0)