Java 并发编程的艺术第2版学习笔记
原书:《Java 并发编程的艺术第2版》 | 作者:方腾飞 魏鹏 程晓明 | 2023 年 9 月 | 机械工业出版社
1.3.2 等待/通知机制 | 15 页
生产者消费者模型是一个非常经典的并发模型,其中生产者和消费者之间通过一个共享的对象进行通信。在 Java 中,可以通过 wait
、notify
和 notifyAll
方法来实现这种通信机制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
| import java.text.SimpleDateFormat;
import java.util.Date;
public class WaitNotify {
static boolean flag = true;
static final Object lock = new Object();
public static void main(String[] args) {
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.start();
SleepUtils.second(1);
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
}
static class Wait implements Runnable {
@Override
public void run() {
// 加锁,拥有 lock 的 Monitor
synchronized (lock) {
while (flag) {
try {
print("flag is true.", "wait");
// 释放 lock 的锁
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
print("flag is false", "running");
}
}
}
static class Notify implements Runnable {
@Override
public void run() {
// 加锁,拥有 lock 的 Monitor
synchronized (lock) {
print("hold lock. ", "notify");
lock.notifyAll();
flag = false;
SleepUtils.second(3);
}
synchronized (lock) {
print("hold lock again.", "sleep");
SleepUtils.second(3);
}
}
}
private static void print(String say, String state) {
System.out.println(Thread.currentThread() + " " + say + " " + state + "@ " + now());
}
private static String now() {
return new SimpleDateFormat("HH:mm:ss").format(new Date());
}
}
|
使用 wait()、notify() 和 notifyAll() 指南
- 调用 wait()、notify() 和 notifyAll() 前,必须先对调用对象加锁
- 调用 wait() 方法后,线程状态由 RUNNING 变为 WAITING,并将当前线程放置到对象的等待队列
- 调用 notify() 或 notifyAll() 方法后,等待线程依旧不会从 wait() 返回,需要调用 notify() 或 notifyAll() 的线程释放锁之后,等待线程才有机会从 wait() 返回
- notify() 方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而 notifyAll() 方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由 WAITING 变为 BLOCKED
- 从 wait() 方法返回的前提是获得了调用对象的锁
wait/notify 机制依托于 synchronized 机制,其目的是确保等待线程从 wait() 方法返回时能够感知到通知线程对共享变量的修改。
使用模板
wait 模板
1
2
3
4
5
6
| synchronized (lock) {
while (condition) {
lock.wait();
}
// do something
}
|
notify 模板
1
2
3
4
| synchronized (lock) {
// change condition
lock.notifyAll();
}
|