首页 昆明信息港 下载客户端 关于彩龙 论坛须知

《Java线程与并发编程实战》读书笔记之等待与通知

一、等待通知API

java.lang.Object类提供了一套等待/通知的API,由三个wait()方法、一个notify()方法和一个notifyAll()方法组成。 wait()方法用于等待某个条件成立,当条件成立时,notify()和notifyAll()方法通知处于等待中的线程。

void wait() 导致当前线程一直处于等待状态,知道另外的线程调用了这个对象的notify()或者notifyAll()方法,又或者一直等待其他的线程中断当前等待的线程。

void wait(long timeout) 导致当前线程一致处于等待状态,知道另外的线程调用这个对象的notify()或notifyAll()方法,或者等待特定的毫秒数(由timeout确定),又或者一直等待到其他的线程中断当前等待的线程。当timeout为负数的时候,这个方法会抛出java.lang.IllegalArgumentException。

void wait(long timeout, int nanos) 导致当前线程一直处于等待状态,直到另外的线程调用这个对象的notify()或者notifyAll()方法,或者等待特定的毫秒(由timeout确定)和纳秒数(由nanos确定),又或者一直等待到其他的线程中断当前等待的线程。当timeout是负数、nanos是负数或者nanos大于999999的时候,这个方法抛出java.lang.IllegalArgumentException。

若当前线程开始或正在等待通知,任一线程中断了它,这三个wait()方法会抛出java.lang.InterruptedException。此时,当前线程的中断状态会被清除。 对象的waint()方法被调用时,线程会放弃对象关联的监听器的所有权。

void notify() 唤醒正在等待该对象监听器的单条线程。如果有几条线程在该对象上等待,其中某一条会被挑选出来唤醒,这种选择是随意的且取决于具体实现。除非当前的线程释放了该对象上的锁,被唤醒的线程仍不能执行。被唤醒的线程跟平常一样,同其他可能活跃的线程一起竞争在该对象上进行同步。换句话说,被唤醒的线程在接下来锁住对象这件事上,既没有优势也没有劣势。

void notifyAll() 唤醒这咋等待该对象监听器上的全部线程。除非当前的线程释放了该对象上的锁,这些被唤醒的线程仍不能执行。被唤醒的线程跟平常一样,同其他可能活跃的线程一起竞争在该对象上进行同步。换句话说,被唤醒的线程在接下来锁住对象这件事上,既没有优势也没有劣势。

二、注意事项

这组API利用了一个对象的条件队列,该队列用于存储那些等待某个条件成立的线程。这些等待的线程称为等待集合。由于该队列和对象的锁紧紧捆绑在一起,以上5个方法必须在同步的上下文中被调用,否则会抛出java.lang.IllegalMonitorStateException。 wait()调用示例

synchronized(obj){

    while([条件不成立]){

         obj.wait();

     }

    // 后续处理

}

wait()方法在一个同步块中调用,该同步块同步的对象和调用wait()方法的对象是一样的。由于有假华兴的可能性(线程不是因为通知、中断或者超时被唤醒),wait()方法在一个while循环中使用,这个循环会测试是否满足条件,并且当条件不满足时重新运行wait()方法。while循环退出之后,条件成立了,和条件相应的动作会被执行。

notify()方法调用示例

synchronized(obj){

      // set the condition

      obj.notify();

}

注意notify()方法是从临界区中调用的,这个临界区和wait()方法所在的临界区一样,被同一个对象(obj)所保护,并且也使用了同一个对象引用来调用notify()方法。

notify()和notifyAll()方法如何选择? 在应用中只有两条线程并且某条线程偶尔等待、需要被另一条线程通知的时候使用notify()方法,否则使用notifyAll()方法。

网友评论

1条评论

发表

网友评论

1条评论

发表

最新评论

rust 5 0

09月28日 15:15

推荐文章

彩龙

Copyright © 2008-2021 彩龙社区 版权所有 All Rights Reserved.

免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。

经营许可证编号:滇B2-20090009-7

下载我家昆明APP 下载彩龙社区APP