Condition 接口详解

举报
JavaEdge 发表于 2022/03/11 23:38:19 2022/03/11
【摘要】 JDK5 时提供。条件队列 ConditionObject 实现了 Condition 接口Condition 将对象监视方法(wait,notify和notifyAll)分解为不同的对象,从而通过与任意Lock实现结合使用,从而使每个对象具有多个wait-sets。 当 Lock 替换了 synchronized 方法和语句的使用,Condition 就可以替换了Object监视器方法的使...

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()

  • 唤醒条件队列中的所有线程
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。