Module  java.base

Interface Condition

  • 所有已知实现类:
    AbstractQueuedLongSynchronizer.ConditionObjectAbstractQueuedSynchronizer.ConditionObject


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

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

    一个Condition实例本质上绑定到一个锁。 要为特定的Lock实例获取Condition实例,请使用其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(); }
       }
     } 
    ArrayBlockingQueue类提供此功能,因此没有理由实现此示例使用类。)

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

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

    除非另有说明,传递任何参数的null值将导致抛出NullPointerException

    实施注意事项

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

    条件等待(可中断,不可中断和定时)的三种形式在一些平台上的易用性和性能特征可能不同。 特别地,可能难以提供这些特征并保持特定的语义,例如排序保证。 此外,中断线程实际挂起的能力可能并不总是在所有平台上实现。

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

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

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

    从以下版本开始:
    1.5
    • 方法摘要

      所有方法  接口方法  抽象方法 
      Modifier and Type 方法 描述
      void await​()
      导致当前线程等到发信号或 interrupted
      boolean await​(long time, TimeUnit unit)
      使当前线程等待直到发出信号或中断,或指定的等待时间过去。
      long awaitNanos​(long nanosTimeout)
      使当前线程等待直到发出信号或中断,或指定的等待时间过去。
      void awaitUninterruptibly​()
      使当前线程等待直到发出信号。
      boolean awaitUntil​(Date deadline)
      使当前线程等待直到发出信号或中断,或者指定的最后期限过去。
      void signal​()
      唤醒一个等待线程。
      void signalAll​()
      唤醒所有等待线程。
    • 方法详细信息

      • await

        void await​()
            throws InterruptedException
        导致当前线程等到发信号或interrupted

        与此相关的锁Condition以原子方式释放,并且当前线程用于线程调度目的,禁用并一直处于休眠状态的四两件事发生对象

        • 一些其他线程调用signal()方法,这个Condition和当前线程恰好被选为被唤醒的线程; 要么
        • 一些其他线程调用signalAll()方法为这个Condition ; 要么
        • 一些其他线程当前线程为interrupts ,并支持线程中断中断; 要么
        • 发生“ 虚假唤醒 ”。

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

        如果当前线程:

        • 在进入该方法时设置了中断状态; 要么
        • interrupted等待和中断螺纹悬挂支持,
        那么抛出InterruptedException并清除当前线程的中断状态。 在第一种情况下,没有规定在释放锁之前是否发生中断测试。

        实施注意事项

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

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

        异常
        InterruptedException - 如果当前线程中断(并且支持线程中断的中断)
      • awaitUninterruptibly

        void awaitUninterruptibly​()
        使当前线程等待直到发出信号。

        与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的三种情况之一发生:

        • 一些其它线程调用signal()方法本Condition和当前线程碰巧被选择作为被唤醒线程; 要么
        • 一些其他线程调用signalAll()方法为这个Condition ; 要么
        • 发生“ 虚假唤醒 ”。

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

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

        实施注意事项

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

      • awaitNanos

        long awaitNanos​(long nanosTimeout)
                 throws InterruptedException
        使当前线程等待直到发出信号或中断,或指定的等待时间过去。

        与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的五件事情发生对象

        • 一些其它线程调用signal()方法本Condition和当前线程碰巧被选择作为被唤醒线程; 要么
        • 一些其他线程调用signalAll()方法为这个Condition ; 要么
        • 一些其他线程当前线程为interrupts ,并支持线程中断中断; 要么
        • 指定的等待时间过去了; 要么
        • 发生“ 虚假唤醒 ”。

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

        如果当前线程:

        • 在进入该方法时设置了中断状态; 要么
        • interrupted等待和中断螺纹悬挂支持,
        那么抛出InterruptedException并清除当前线程的中断状态。 在第一种情况下,没有规定在释放锁之前是否发生中断测试。

        该方法返回时给出所提供的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 ),实现必须记录该事实。

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

        参数
        nanosTimeout - 等待的最长时间,以纳秒为单位
        结果
        估计nanosTimeout值减去等待从此方法返回的时间。 可以使用正值作为随后调用此方法的参数,以完成等待所需时间。 小于或等于零的值表示没有时间。
        异常
        InterruptedException - 如果当前线程被中断(并且支持线程中断的中断)
      • await

        boolean await​(long time,
                      TimeUnit unit)
               throws InterruptedException
        使当前线程等待直到发出信号或中断,或指定的等待时间过去。 这种方法在行为上等同于:
          awaitNanos(unit.toNanos(time)) > 0 
        参数
        time - 等待的最长时间
        unit - time参数的时间单位
        结果
        false如果等待时间可以从方法返回之前经过,否则 true
        异常
        InterruptedException - 如果当前线程被中断(并且支持线程中断的中断)
      • awaitUntil

        boolean awaitUntil​(Date deadline)
                    throws InterruptedException
        使当前线程等待直到发出信号或中断,或者指定的最后期限过去。

        与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的五件事情发生对象

        • 一些其它线程调用signal()方法本Condition和当前线程碰巧被选择作为被唤醒线程; 要么
        • 一些其他线程调用signalAll()方法为这个Condition ; 要么
        • 一些其他线程当前线程interrupts ,并支持线程中断中断; 要么
        • 规定的期限过去了; 要么
        • 发生“ 虚假唤醒 ”。

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

        如果当前线程:

        • 在进入该方法时设置了中断状态; 要么
        • interrupted ,等待和中断螺纹悬挂支持,
        那么抛出InterruptedException并清除当前线程的中断状态。 在第一种情况下,没有规定在释放锁之前是否发生中断测试。

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

           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 ),实现必须记录该事实。

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

        参数
        deadline - 绝对等待的时间
        结果
        false如果截止日期已过,返回时,其他 true
        异常
        InterruptedException - 如果当前线程中断(并且支持线程中断的中断)
      • signal

        void signal​()
        唤醒一个等待线程。

        如果任何线程正在等待此条件,则选择一个线程进行唤醒。 那么线程必须在从await返回之前重新获取锁。

        实施注意事项

        当调用此方法时,实现可能(通常是)要求当前线程保存与此Condition相关联的锁。 执行必须记录此前提条件,如果不保持锁定,则采取任何措施。 通常,会抛出异常,如IllegalMonitorStateException

      • signalAll

        void signalAll​()
        唤醒所有等待线程。

        如果任何线程正在等待这个条件,那么它们都被唤醒。 每个线程必须重新获取锁,才能从await返回。

        实施注意事项

        当调用此方法时,实现可能(通常是)要求当前线程保存与此Condition相关联的锁。 执行必须记录此前提条件,如果不保持锁定,则采取任何措施。 通常,将抛出例如IllegalMonitorStateException异常。