等待通知机制

文章目录
  1. 1. 等待方遵循原则
  2. 2. 通知方遵循原则
  3. 3. 代码示例

等待方遵循原则

  1. 获取对象的锁
  2. 如果条件不满足,那么调用对象的wait(),被通知后仍要检查条件
  3. 条件满足则执行对应的逻辑

伪代码如下:

1
2
3
4
5
6
synchronized( 对象 ) {
while ( 条件不满足 ) {
对象.wait();
}
对应的处理逻辑
}

通知方遵循原则

  1. 获得对象的锁
  2. 改变条件
  3. 通知所有等待在对象上的线程

伪代码如下:

1
2
3
4
synchronized ( 对象 ) {
改变条件
对象.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
66
67
68
69
70
71
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object();

public static void main(String[] args) throws InterruptedException {
Thread waitThread = new Thread(new Wait(),"WaitThread");
waitThread.start();

TimeUnit.SECONDS.sleep(1);

Thread notifyThread = new Thread(new Notify(),"NotifyThread");
notifyThread.start();

TimeUnit.SECONDS.sleep(1);
}

static class Wait implements Runnable {
//加锁,拥有Lock的Monitor
public void run() {
synchronized (lock) {
//当条件不满足时,wait,释放lock的锁
while (flag) {
try {
System.out.println(Thread.currentThread() + "flag is true. wait @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//条件满足时,完成工作
System.out.println(Thread.currentThread() + "flag is false. wait @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}

static class Notify implements Runnable {
//加锁,拥有lock的Monitor
public void run() {
synchronized (lock) {
//获取lock的锁,然后进行通知,通知时不会释放lock的锁
//直到当前线程释放了lock后,WaitThread才能从wait方法返回
System.out.println(Thread.currentThread() + "hold lock. notify @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));

lock.notifyAll();//WaitThread从等待队列进入同步队列,通知时不会释放lock的锁
flag = false;

try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

//再次加锁
synchronized (lock){
System.out.println(Thread.currentThread() + "hold lock again. notify @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
}

try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}

}//当前线程释放lock之后,WaitThread从同步队列出去,尝试获取锁
}
}

运行结果:

1
2
3
4
Thread[WaitThread,5,main]flag is true. wait @ 21:35:39
Thread[NotifyThread,5,main]hold lock. notify @ 21:35:40
Thread[NotifyThread,5,main]hold lock again. notify @ 21:35:45
Thread[WaitThread,5,main]flag is false. wait @ 21:35:45