Most visited

Recently visited

Added in API level 1

Condition

public interface Condition

java.util.concurrent.locks.Condition
Known Indirect Subclasses


Condition因素出Object监视器方法( waitnotifynotifyAll )成不同的对象,以得到具有多个等待集的每个对象,通过将它们与使用任意的组合的效果Lock实现。 如果Lock取代synchronized方法和语句的使用,则Condition将取代使用对象监视器方法。

条件(也称为条件队列条件变量 )为一个线程暂停执行(“等待”)提供了一种方法,直到另一个线程通知某些状态条件现在可能为真。 因为访问这个共享状态信息发生在不同的线程中,所以它必须被保护,所以某种形式的锁与该条件相关联。 等待条件的关键属性是它自动释放关联的锁并挂起当前线程,就像Object.wait一样。

Condition实例内在地绑定到一个锁。 为了获得Condition实例特定Lock实例使用其newCondition()方法。

作为一个例子,假设我们有一个支持puttake方法的有界缓冲区。 如果一个take试图在一个空的缓冲区上,那么该线程将会阻塞,直到一个项目变为可用; 如果put试图在一个完整的缓冲区上,那么该线程将阻塞,直到有空间可用。 我们希望继续等待put线程和take线程放入不同的等待集中,这样我们就可以使用优化,只在缓冲区中的项目或空间变为可用时通知单个线程。 这可以使用两个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();
     }
   }
 }
 
(The ArrayBlockingQueue class provides this functionality, so there is no reason to implement this sample usage class.)

Condition实现可以提供与Object监视器方法不同的行为和语义,例如保证通知的排序,或者在执行通知时不需要锁定。 如果实现提供了这种专用语义,那么实现必须记录这些语义。

请注意, Condition实例只是普通对象,并且本身可以用作synchronized语句中的目标,并且可以调用其自己的监视器waitnotify方法。 获取Condition实例的监视器锁或使用其监视器方法与获取与该Lock关联的Condition或使用其waitingsignalling方法没有特定的关系。 为避免混淆,建议您不要以这种方式使用Condition实例,除非在其自己的实现中。

除非另有说明, null为任何参数传递 null值都会导致引发 NullPointerException

Implementation Considerations

在等待Condition时,通常会允许发生“ 虚假唤醒 ”,作为底层平台语义的让步。 这对大多数应用程序几乎没有实际影响,因为Condition应该始终等待循环,测试正在等待的状态谓词。 一个实现可以自由地消除虚假唤醒的可能性,但建议应用程序员总是假设它们可能发生,因此总是等待循环。

等待状态(可中断,不可中断和定时)的三种形式可能会因其在某些平台上的易用性及其性能特点而有所不同。 特别是,可能很难提供这些功能并保持特定的语义,如订购保证。 此外,中断线程的实际中断的能力可能并不总是可行的,以在所有平台上实现。

因此,实现不需要为所有三种形式的等待定义完全相同的保证或语义,也不需要支持中断实际挂起的线程。

需要一个实现来清楚地记录每个等待方法提供的语义和保证,并且当实现确实支持中断线程暂停时,它必须遵守此接口中定义的中断语义。

由于中断通常意味着取消,并且检查中断通常很少发生,所以实现可以有利于响应正常方法返回的中断。 即使可以显示中断发生在可能解除线程的另一个操作之后,也是如此。 一个实现应该记录这种行为。

Summary

Public methods

abstract void await()

导致当前线程等待,直到它被发信号或 interrupted

abstract boolean await(long time, TimeUnit unit)

导致当前线程等待,直到它发出信号或中断,或经过指定的等待时间。

abstract long awaitNanos(long nanosTimeout)

导致当前线程等待,直到它发出信号或中断,或经过指定的等待时间。

abstract void awaitUninterruptibly()

导致当前线程等待直到它被发送信号。

abstract boolean awaitUntil(Date deadline)

导致当前线程等待,直到它被发信号通知或中断,或经过指定的截止时间。

abstract void signal()

唤醒一个等待线程。

abstract void signalAll()

唤醒所有等待的线程。

Public methods

await

Added in API level 1
void await ()

导致当前线程等待直到它被发信号或 interrupted

与此 Condition关联的锁被自动释放,并且当前线程因线程调度目的而被禁用,并且处于休眠状态,直到发生四件事 之一

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
  • A "spurious wakeup" occurs.

在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件相关的锁。 当线程返回时,它保证保持这个锁。

如果当前线程:

  • has its interrupted status set on entry to this method; or
  • is interrupted while waiting and interruption of thread suspension is supported,
then InterruptedException is thrown and the current thread's interrupted status is cleared. It is not specified, in the first case, whether or not the test for interruption occurs before the lock is released.

实施注意事项

当调用此方法时,假定当前线程保持与此Condition关联的锁。 这是由实施来决定是否是这种情况,如果没有,如何回应。 通常情况下,将抛出异常(如IllegalMonitorStateException ),并且实现必须记录该事实。

一个实现可以有利于响应一个信号响应正常方法返回的中断。 在这种情况下,实现必须确保信号被重定向到另一个等待线程(如果有的话)。

Throws
InterruptedException if the current thread is interrupted (and interruption of thread suspension is supported)

await

Added in API level 1
boolean await (long time, 
                TimeUnit unit)

导致当前线程等待,直到它发出信号或中断,或经过指定的等待时间。 此方法在行为上等同于:

 awaitNanos(unit.toNanos(time)) > 0

Parameters
time long: the maximum time to wait
unit TimeUnit: the time unit of the time argument
Returns
boolean false if the waiting time detectably elapsed before return from the method, else true
Throws
InterruptedException if the current thread is interrupted (and interruption of thread suspension is supported)

awaitNanos

Added in API level 1
long awaitNanos (long nanosTimeout)

导致当前线程等待,直到它发出信号或中断,或经过指定的等待时间。

与此条件相关的锁被自动释放,并且当前线程因为线程调度目的而被禁用,并且处于休眠状态,直到发生五件事 之一

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
  • The specified waiting time elapses; or
  • A "spurious wakeup" occurs.

在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件相关的锁。 当线程返回时,它保证保持这个锁。

如果当前线程:

  • has its interrupted status set on entry to this method; or
  • is interrupted while waiting and interruption of thread suspension is supported,
then InterruptedException is thrown and the current thread's interrupted status is cleared. It is not specified, in the first case, whether or not the test for interruption occurs before the lock is released.

该方法在返回时返回估计的等待的剩余纳秒数,或者返回时提供nanosTimeout值,或者如果超时则返回小于或等于零的值。 此值可用于确定在等待返回但等待状态仍不成立的情况下是否需要等待多长时间。 此方法的典型用法采用以下形式:

 boolean aMethod(long timeout, TimeUnit unit) {
   long nanos = unit.toNanos(timeout);
   lock.lock();
   try {
     while (!conditionBeingWaitedFor()) {
       if (nanos <= 0L)
         return false;
       nanos = theCondition.awaitNanos(nanos);
     }
     // ...
   } finally {
     lock.unlock();
   }
 }

设计说明:此方法需要纳秒参数,以避免报告剩余时间中的截断错误。 这种精确的损失会使程序员很难确保总等待时间不会比重新等待时指定的系统更短。

实施注意事项

当这个方法被调用时,当前线程被认为保持与这个Condition相关的锁。 这是由实施来决定是否是这种情况,如果没有,如何回应。 通常情况下,将抛出异常(如IllegalMonitorStateException ),并且实现必须记录该事实。

一个实现可以有利于响应一个中断响应一个正常的方法返回一个信号,或通过指示经过了指定的等待时间。 在任何一种情况下,实现都必须确保将信号重定向到另一个等待线程(如果有)。

Parameters
nanosTimeout long: the maximum time to wait, in nanoseconds
Returns
long an estimate of the nanosTimeout value minus the time spent waiting upon return from this method. A positive value may be used as the argument to a subsequent call to this method to finish waiting out the desired time. A value less than or equal to zero indicates that no time remains.
Throws
InterruptedException if the current thread is interrupted (and interruption of thread suspension is supported)

awaitUninterruptibly

Added in API level 1
void awaitUninterruptibly ()

导致当前线程等待直到它被发送信号。

与此条件相关联的锁被自动释放,当前线程因为线程调度目的而被禁用,并且处于休眠状态,直到发生以下三件事 之一

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • A "spurious wakeup" occurs.

在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件相关的锁。 当线程返回时,它保证保持这个锁。

如果当前线程的中断状态在进入此方法时被设置,或者在等待时为interrupted ,它将继续等待直到发出信号。 当它最终从这个方法返回时,它的中断状态仍将被设置。

实施注意事项

当调用此方法时,假定当前线程保存与此Condition关联的锁。 这是由实施来决定是否是这种情况,如果没有,如何回应。 通常情况下,将抛出异常(如IllegalMonitorStateException ),并且实现必须记录该事实。

awaitUntil

Added in API level 1
boolean awaitUntil (Date deadline)

导致当前线程等待,直到它被发信号通知或中断,或经过指定的截止时间。

与此条件相关的锁被自动释放,并且当前线程因为线程调度目的而被禁用,并且处于休眠状态,直到发生五件事 之一

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
  • The specified deadline elapses; or
  • A "spurious wakeup" occurs.

在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件相关的锁。 当线程返回时,它保证保持这个锁。

如果当前线程:

  • has its interrupted status set on entry to this method; or
  • is interrupted while waiting and interruption of thread suspension is supported,
then InterruptedException is thrown and the current thread's interrupted status is cleared. It is not specified, in the first case, whether or not the test for interruption occurs before the lock is released.

返回值表示截止日期是否已过,可以如下使用:

 boolean aMethod(Date deadline) {
   boolean stillWaiting = true;
   lock.lock();
   try {
     while (!conditionBeingWaitedFor()) {
       if (!stillWaiting)
         return false;
       stillWaiting = theCondition.awaitUntil(deadline);
     }
     // ...
   } finally {
     lock.unlock();
   }
 }

实施注意事项

当调用此方法时,假定当前线程保持与此Condition关联的锁。 这是由实施来决定是否是这种情况,如果没有,如何回应。 通常情况下,将抛出异常(如IllegalMonitorStateException ),并且实现必须记录该事实。

一个实现可以有利于响应一个中断而不是响应一个信号的正常方法返回,或者指示通过指定的最后期限。 在任何一种情况下,实现都必须确保将信号重定向到另一个等待线程(如果有)。

Parameters
deadline Date: the absolute time to wait until
Returns
boolean false if the deadline has elapsed upon return, else true
Throws
InterruptedException if the current thread is interrupted (and interruption of thread suspension is supported)

signal

Added in API level 1
void signal ()

唤醒一个等待线程。

如果有任何线程正在等待这种情况,则选择一个唤醒。 该线程必须在从await返回之前重新获得该锁。

实施注意事项

当这个方法被调用时,一个实现可能(并且典型地)要求当前线程持有与这个Condition相关的锁。 实现必须记录这个先决条件以及如果不锁定所采取的任何行动。 通常,会抛出一个例外,如IllegalMonitorStateException

signalAll

Added in API level 1
void signalAll ()

唤醒所有等待的线程。

如果有线程在等待这种情况,那么它们都会被唤醒。 每个线程在从await返回之前都必须重新获取该锁。

实施注意事项

实现可能(并且通常确实)要求当调用此方法时当前线程保存与此Condition相关联的锁。 实现必须记录这个先决条件以及如果不锁定所采取的任何行动。 通常情况下,会抛出一个异常,如IllegalMonitorStateException

Hooray!