Wait&Notify的通知机制

Posted by Liao on 2019-10-12

Wait&Notify的通知机制

​ wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或notifyAll方法才可另其继续执行。经典的生产者、消费者模式即是使用wait/notify机制得以完成。

1.当线程A(消费者)调用wait()时,A会把锁释放出来,使自己进入等待状态,同时加入“锁对象”的等待队列。

2.线程B获取锁后,调用notify()通知“锁对象”的等待队列,使得线程A从等待队列进入阻塞队列。

3.线程A进入阻塞队列后,直到线程B释放锁,线程A竞争到锁之后才能继续执行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
public class ThreadTest {

static final Object obj = new Object(); //对象锁

private static boolean flag = false;

public static void main(String[] args) throws Exception {

Thread consume = new Thread(new Consume(), "Consume");
Thread produce = new Thread(new Produce(), "Produce");
consume.start();
Thread.sleep(1000);
produce.start();

try {
produce.join();
consume.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

// 生产者线程
static class Produce implements Runnable {

@Override
public void run() {

synchronized (obj) {
System.out.println("进入生产者线程");
System.out.println("生产");
try {
TimeUnit.MILLISECONDS.sleep(2000); //模拟生产过程
flag = true;
obj.notify(); //通知消费者
TimeUnit.MILLISECONDS.sleep(1000); //模拟其他耗时操作
System.out.println("退出生产者线程");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

//消费者线程
static class Consume implements Runnable {

@Override
public void run() {
synchronized (obj) {
System.out.println("进入消费者线程");
System.out.println("wait flag 1:" + flag);
while (!flag) { //判断条件是否满足,若不满足则等待
try {
System.out.println("还没生产,进入等待");
obj.wait();
System.out.println("结束等待");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("wait flag 2:" + flag);
System.out.println("消费");
System.out.println("退出消费者线程");
}

}
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
进入消费者线程

wait flag 1:false

还没生产,进入等待

进入生产者线程

生产

退出生产者线程

结束等待

wait flag 2:true

消费

退出消费者线程

1.wait()

1
public final void wait()  throws InterruptedException,IllegalMonitorStateException

​ wait()用于把线程置于休眠状态,直至接到通知或被中断。

  • 在调用wait()之前,线程必须获得对象“对象级别锁”,即只能在同步方法或者同步代码块中调用wait()。
  • 进入wait()中,当前线程释放锁。
  • 在从wait()返回前,除当前线程外的其他线程会竞争获得锁。
  • 若没有竞争到适当的锁,则抛出IllegalMonitorStateException。

程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

2.notify()

1
public final native void notify() throws IllegalMonitorStateException

​ 该方法用来通知那些可能等待该对象的对象锁的其他线程(notify()方法用于通知调用wait()释放锁的线程从等待状态进入阻塞状态)。

  • 如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知,并使它等待获取该对象的“对象锁”(就是获得了锁),别的线程不能访问它。
  • 调用notify()方法后,当前线程不会马上释放该对象的锁,wait()所在的线程也不会马上获取该对象的锁,要等程序退出synchronized代码块后,当前线程才会释放锁,wait()所在的线程才能获得该对象锁。

???线程获得锁之后???