Java并发包之Condition接口

前言

  • 传统上,我们可以通过synchronized关键字 + wait + notify/notifyAll来实现多个线程之间的协调与通信,整个过程都是由JVM来帮助我们实现的;开发者无需(也是无法)了解底层的实现细节,一个对象有一个wait set
  • 从JDK 5开始,并发包提供了Lock,Condition(await与signal/signalAll)来实现多个线程之间的协调与通信,整个过程都是由开发者来控制的,而且相比手传统方式,更加灵活,功能也更加强大,一个对象可以有多个wait set

老样子,继续看文档,看看Condition接口的作用

image.png

  • ConditionObject监视器方法( (Object类)wait 、 notifynotifyAll分解为不同的对象,通过将它们与任意Lock实现的使用相结合(绑定),产生每个对象具有多个等待集的效果。 Lock代替了synchronized方法和语句的使用,而Condition代替了对象监视器方法的使用
  • Condition(也称为条件队列或条件变量)为一个线程提供了一种挂起执行(“等待”)的方法,直到另一个线程通知某个状态条件现在可能为true。 因为对这个共享状态信息的访问发生在不同的线程中,它必须受到保护所以某种形式的Lock与Condition相关联(绑定)。 等待中的Condition所提供的关键属性是它会自动的释放关联的锁并挂起当前线程,就像Object.wait一样。
  • Condition实例客观上要绑定到锁。 要获取特定Lock实例的Condition实例,请使用其newCondition()方法。

image.png

  • Condition实现可以提供与Object监视器方法不同的行为和语义,例如保证通知的顺序,或者在执行通知时不需要持有锁。 如果实现提供了这样的专门语义,那么实现必须记录这些语义。
  • 请注意, Condition实例只是普通对象,它们本身可以用作synchronized语句中的目标,并且可以调用它们自己的监视器waitnotification方法。 获取Condition实例的监视器锁,或使用其监视器方法,与获取与该Condition关联的Lock或其等待(await)和信号(signal)方法的使用没有特定的关系。 建议您不要以这种方式使用Condition实例以避免混淆,除非在它们自己的实现中。
  • 除非另有说明,否则为任何参数传递null值都将导致抛出NullPointerException

介绍Condition中的方法

void await() throws InterruptedException;

image.png

  • 使当前线程等待,直到它收到信号(signal)或被中断(interrupted)
  • 与此Lock相关的Condition是自动释放锁的,并且当前线程用于线程调度目的,禁用并一直处于休眠状态直到下面四个中的一个件事发生:
    • 某个其他线程为此Condition调用了signal方法,并且恰好选择了当前线程作为要唤醒的线程; 或者
    • 其他一些线程为此Condition调用signalAll方法; 或者
    • 其他一些线程中断当前线程,支持线程挂起中断; 或者
    • 发生“虚假唤醒”。(没有被其他线程通知,却唤醒了)
  • 在所有情况下,在此方法可以返回当前线程之前,必须重新获取与此条件关联的锁。 当线程返回时,它保证持有这个锁。
  • 如果当前线程:
    • 在进入此方法时设置其中断状态; 或者
    • 等待时被中断,支持线程挂起中断,

    然后抛出InterruptedException并清除当前线程的中断状态。 对于第一种情况,在释放锁之前是否进行中断测试没有规定

void awaitUninterruptibly();

  • 与上面的await一样
  • 多了一条如下:

image.png

  • 如果当前线程在进入该方法时被设置为中断状态,或者在等待时被中断,则将继续等待直到收到信号(signal)。 当它最终从这个方法返回时,它的中断状态仍在。(总之就是不可中断)

long awaitNanos(long nanosTimeout) throws InterruptedException;

  • 注意返回值为long

image.png

  • 使当前线程等待,直到它收到信号(signal)或被中断,或者指定的等待时间过去
  • 与此Condition关联的锁被自动释放,当前线程因线程调度目的而被禁用并处于休眠状态,直到发生以下五件事之一:
    • 某个其他线程为此Condition调用了signal方法,并且恰好选择了当前线程作为要唤醒的线程;或者
    • 其他一些线程为此Condition调用signalAll方法; 或者
    • 其他一些线程中断当前线程,线程挂起中断被支持; 或者
    • 指定的等待时间过去; 或者
    • 发生“虚假唤醒”。
  • 在所有情况下,在此方法可以返回当前线程之前,必须重新获取与此条件关联的锁。当线程返回时,它保证持有这个锁。
  • 如果当前线程:
    • 在进入此方法时设置其中断状态; 或者
    • 等待时被中断,支持线程挂起中断,

    然后抛出InterruptedException并清除当前线程的中断状态。 对于第一种情况,在释放锁之前是否进行中断测试没有规定。

  • 给定返回时提供的nanosTimeout值,该方法返回剩余等待纳秒数的估计值(参数减去被唤醒是时间数),如果超时则返回小于或等于 0 的值(毕竟有误差,但不会小于0太多)。 此值可用于确定在等待返回但等待条件仍然不成立的情况下是否重新等待以及重新等待多长时间。

image.png

参数:
nanosTimeout – 等待的最长时间,以纳秒为单位
返回值:
nanosTimeout值减去等待从该方法返回所花费的时间的估计值。 可以使用正值作为对该方法的后续调用的参数,以完成等待所需的时间。 小于或等于零的值表示没有剩余时间。
抛出:
InterruptedException – 如果当前线程被中断(并且支持线程挂起中断)

boolean await(long time, TimeUnit unit) throws InterruptedException;

image.png

  • 使当前线程等待,直到它被发出信号或被中断,或者指定的等待时间过去。 此方法在行为上等效于:
    awaitNanos(unit.toNanos(time)) > 0

参数:
时间 – 等待的最长时间
unittime参数的时间单位
返回值:
如果在从方法返回之前可检测到等待时间已经过去,则为false ,否则为true
抛出:
InterruptedException – 如果当前线程被中断(并且支持线程挂起中断)

boolean awaitUntil(Date deadline) throws InterruptedException;

image.png

  • 其实和 boolean await(long time, TimeUnit unit) 类似

返回值:
如果返回时截止日期已过则为false ,否则为true

void signal();

image.png

  • 唤醒一个等待线程。
  • 如果有任何线程正在等待这个condition,则选择一个线程来唤醒。 被唤醒的线程必须在从await返回(await结束)之前重新获取锁

void signalAll();

image.png

  • 唤醒所有等待的线程。
  • 如果任何线程正在等待这种情况,那么它们都会被唤醒。 每个线程必须重新获取锁才能从await返回
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享