java-doc-wait与notify

wait和notify、notifyall

wait方法导致当前线程等待, 加入该对象的等待集合中, 并且放弃当前持有的对象锁。
notify/notifyAll方法唤醒一个或所有正在等待这个对象锁的线程。

注意:

  • 虽然会wait自动解锁, 但是对顺序有要求, 如果在notify被调用之后, 才开始wait方法
    的调用, 线程会永远处于WAITING状态
  • 这些方法只能由同一对象锁的持有者线程调用, 也就是写在同步块里面, 否则会抛出
    IllegalMonitorStateException异常。
  • wait()和notify()方法必须在synchronized标识的方法内使用。
  • wait()方法调用后,会破坏原子性,线程被中断后,wait后面的方法将不在执行。

示例

  • wait先调用
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
class Q
{
int n;
boolean valueSet = false;

synchronized int get()
{
// 使用等待条件,循环调用wait
while(!valueSet) {
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedExeption caught");
}
}

System.out.println("Got :" + n);
valueSet = false;
notify();
return n;
}

synchronized void put(int n)
{
// 使用等待条件,循环调用wait
while(valueSet) {
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedExeption caught");
}
}

this.n = n;
valueSet = true;
System.out.println("Put :" + n);
notify();
}
}

class Producer implements Runnable
{
Q q;

Producer(Q q)
{
this.q =q;
new Thread(this, "Producer").start();
}

public void run()
{
int i = 0;

while(true) {
q.put(i++);
}
}
}

class Consumer implements Runnable
{
Q q;

Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}

public void run()
{
while(true) {
q.get();
}
}
}

public class LearnThreadComm
{
public static void main(String args[])
{
Q q = new Q();
new Producer(q);
new Consumer(q);

System.out.println("Stop");

// 结果
// Put :1
// Got :1
// Put :2
// Got :2
// Put :3
// Got :3
// Put :4
// Got :4
// ...
}
}
  • notify先调用,导致死锁
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
public class LearnWait1 {
public static Object iceCream = null;

public static void main(String[] args) {
LearnWait1 wai = new LearnWait1();
try {
wai.DeadLock();
} catch (Exception e) {
e.printStackTrace();
}
}

public void DeadLock() throws Exception {
//开启一个线程, 代表小朋友
new Thread(() -> {
if (iceCream == null) { //若没有冰激凌
try {
Thread.sleep(5000L);
System.out.println("没有冰激凌, 小朋友不开心, 等待...");
synchronized (this){
this.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
System.out.println("小朋友买到冰激凌, 开心回家");
}).start();
Thread.sleep(3000L); // 3秒之后
iceCream = new Object(); // 店员做了一个冰激凌
synchronized (this){ //通知小朋友
this.notifyAll();
}
System.out.println("通知小朋友");
}
}