Condition将Object监视器方法( wait 、 notify和notifyAll )分解为不同的对象,通过将它们与任意Lock实现的使用结合起来,使每个对象具有多个等待集的效果。 Lock代替了synchronized方法和语句的使用, Condition代替了 Object 监视器方法的使用。 条件(也称为条件队列或条件变量)为一个线程提供了一种暂停执行(“等待”)的方法,直到另一个线程通知某个状态条件现在可能为真。因为对这种共享状态信息的访问发生在不同的线程中,所以它必须受到保护,所以某种形式的锁与条件相关联。等待条件提供的关键属性是它以原子方式释放关联的锁并挂起当前线程,就像Object.wait一样。 Condition实例本质上绑定到锁。要获取特定Lock实例的Condition实例,请使用其newCondition()方法。 例如,假设我们有一个支持put和take方法的有界缓冲区。如果take空缓冲区上尝试获取,则线程将阻塞,直到项目变得可用;如果在一个完整的缓冲区上尝试put ,则线程将阻塞,直到有空间可用。我们希望继续等待put线程并在单独的等待集中take线程,以便我们可以使用在缓冲区中可用的项目或空间时仅通知单个线程的优化。这可以使用两个Condition实例来实现。
( java.util.concurrent.ArrayBlockingQueue类提供了这个功能,所以没有理由实现这个示例使用类。) Condition实现可以提供与Object监视器方法不同的行为和语义,例如保证通知的顺序,或者在执行通知时不需要持有锁。如果实现提供了这种专门的语义,那么实现必须记录这些语义。 请注意, Condition实例只是普通对象,它们本身可以用作synchronized语句中的目标,并且可以调用它们自己的监视器wait和notification方法。获取Condition实例的监视器锁,或使用其监视器方法,与获取与该Condition关联的Lock或使用其等待和信令方法没有指定关系。为避免混淆,建议不要以这种方式使用Condition实例,除非在它们自己的实现中。 除非另有说明,否则为任何参数传递null值将导致引发NullPointerException 。 实施注意事项 在等待Condition时,通常允许发生“虚假唤醒”,作为对底层平台语义的让步。这对大多数应用程序几乎没有实际影响,因为应始终在循环中等待Condition ,测试正在等待的状态谓词。一个实现可以自由地消除虚假唤醒的可能性,但建议应用程序程序员总是假设它们可以发生,因此总是在循环中等待。 条件等待的三种形式(可中断、不可中断和定时)在某些平台上实现的难易程度和性能特征可能不同。特别是,可能难以提供这些功能并维护特定的语义,例如排序保证。此外,中断线程的实际挂起的能力可能并不总是适用于所有平台。 因此,实现不需要为所有三种等待形式定义完全相同的保证或语义,也不需要支持线程实际挂起的中断。 实现需要清楚地记录每个等待方法提供的语义和保证,并且当实现确实支持线程挂起的中断时,它必须遵守此接口中定义的中断语义。 由于中断通常意味着取消,并且对中断的检查通常不常见,因此实现可以倾向于响应中断而不是正常的方法返回。即使可以证明中断发生在另一个可能已经解除阻塞线程的操作之后也是如此。一个实现应该记录这个行为。
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
使当前线程一直等待,直到它发出信号或中断,或者指定的等待时间过去。 与此条件关联的锁被自动释放,并且当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下五件事之一: 其他某个线程为此Condition调用了signal方法,而当前线程恰好被选为要被唤醒的线程;或者 其他一些线程为此Condition调用signalAll方法;或者 其他一些线程中断当前线程,支持中断线程挂起;或者 指定的等待时间过去;或者 发生“虚假唤醒”。 在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,它保证持有这个锁。 如果当前线程: 在进入此方法时设置其中断状态;或者 等待时被中断,支持线程挂起的中断, 然后抛出InterruptedException并清除当前线程的中断状态。在第一种情况下,没有规定是否在释放锁之前进行中断测试。 给定返回时提供的nanosTimeout值,该方法返回对剩余等待纳秒数的估计,如果超时,则返回小于或等于零的值。在等待返回但等待的条件仍然不成立的情况下,此值可用于确定是否重新等待以及重新等待多长时间。此方法的典型用途采用以下形式:
设计说明:此方法需要纳秒参数,以避免报告剩余时间时出现截断错误。这种精度损失将使程序员难以确保总等待时间不会系统地短于重新等待发生时指定的时间。 实施注意事项 调用此方法时,假定当前线程持有与此Condition关联的锁。由实现决定是否是这种情况,如果不是,如何响应。通常,将抛出异常(例如IllegalMonitorStateException )并且实现必须记录该事实。 与响应信号的正常方法返回或指示指定等待时间的流逝相比,实现更倾向于响应中断。在任何一种情况下,实现都必须确保将信号重定向到另一个等待线程(如果有的话)。 参数: nanosTimeout – 等待的最长时间,以纳秒为单位 回报: nanosTimeout值的估计值减去从该方法返回时等待的时间。一个正值可以用作对该方法的后续调用以完成等待所需时间的参数。小于或等于零的值表示没有剩余时间。 抛出: InterruptedException – 如果当前线程被中断(并且支持线程挂起的中断)。