跳到主要内容

四、wait + notify + notifyAll

一、初识 wait、notify、notifyAll

我们知道由于线程的抢占式执行导致线程之间的调度是随机的,无序的。但是在一些场景下我们有需要合理的协调多个线程的执行顺序。我们知道使用 join 可以控制线程执行顺序,但是 join 只能让一个线程执行完在执行另外一个线程,功能有限。因此我们引入了 waitnotify/notifyAll 这样一组API用来更灵活地控制线程执行的顺序。

举个例子:
file

针对上述情况,我们可以使用 wait/notify 有效解决:

假如张三发现ATM没钱,就(wait)释放锁走出ATM机,并进行阻塞等待(暂时不参与CPU调度,不参与锁竞争),直到有人向ATM机存钱后,此时时机成熟,就可以唤醒(notify)张三,继续参与ATM机锁竞争。

二、wait、notify、notifyAll 功能介绍

1、wait()

> wait():发现条件不满足/时机不成熟,就调用 wait() 阻塞等待,同时释放当前锁,当满足一定条件时可以被唤醒,重新尝试获取这个锁。

> :使用 wait() 阻塞等待会让线程进入WAITING状态

wait等待结束条件:

> 1. 其他线程调用该对象的 notify 方法. > 2. wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间). > 3. 其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

2、notify()

> notify():其他线程构造了一个成熟的条件,就可以调用 notify() 唤醒它。

notify注意事项:

> 1. 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。 > 2. 如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)