等待-通知机制定义解释:
当线程不满足执行条件时,线程进入等待阶段,当条件满足后时,通知线程并唤醒它继续执行,这就时等待-唤醒机制。
Java中的等待唤醒机制实现:
Synchronized来实现等待-通知机制,Java 语言内置的 synchronized 配合 wait()、notify()、notifyAll() 这三个方法实现等待-通知机制。
完整的等待-通知机制实现,线程获取互斥锁,当线程要求的条件不满足,释放互斥锁,进入等待状态,当要求的条件满足,通知等待的线程,重新获取互斥锁。
这个总结恰如其分的总结出线程协作的本质,对与线程协作的设计,我认同书上说的一句话:协作的核心是想清楚协作的共享变量和条件是什么
public class test6 {
public static void main(String[] args) {
waitthread waitthread = new waitthread();
System.out.println("等待线程启动");
waitthread.start();
System.out.println("通知线程启动");
waitthread.fire();
}
public static class waitthread extends Thread {
private volatile boolean fire = false;
@Override
public synchronized void run() {
while (!fire) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("收到通知后打印消息");
}
public synchronized void fire() {
this.fire = true;
notify();
}
}
}
输出结果:
等待线程启动
通知线程启动
收到通知后打印消息
Process finished with exit code 0
使用以上三种方法可以完成多种场景的线程同步问题,下面介绍5种场景如下:
1.生产者/消费者模型
2.同时开始模型
3.主从协作模型
4.主从异步结果协作模型
5.集合点模型
实践是检验真理的唯一标准,以下是代码例子:
1.生产者/消费者模型实践
public class test7 {
public static class MyBlockingQuene {
private volatile int j = 1;
private volatile boolean fire = false;
public synchronized void put() {
while (!fire) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = 0;
while (i < 4 && j < 101) {
System.out.println("线程1打印:" + j);
j++;
i++;
}
fire = false;
notifyAll();
}
public synchronized void take() {
while (fire) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = 0;
while (i < 4 && j < 101) {
System.out.println("线程2打印:" + j);
j++;
i++;
}
fire = true;
notifyAll();
}
}
public static class Producer extends Thread {
MyBlockingQuene myBlockingQuene;
public Producer(MyBlockingQuene myBlockingQuene) {
this.myBlockingQuene = myBlockingQuene;
}
@Override
public void run() {
while (myBlockingQuene.j < 101) {
myBlockingQuene.put();
}
}
}
public static class Consumer extends Thread {
MyBlockingQuene myBlockingQuene;
public Consumer(MyBlockingQuene myBlockingQuene) {
this.myBlockingQuene = myBlockingQuene;
}
@Override
public void run() {
while (myBlockingQuene.j < 101) {
myBlockingQuene.take();
}
}
}
public static void main(String[] args) {
MyBlockingQuene myBlockingQuene = new MyBlockingQuene();
new Producer(myBlockingQuene).start();
new Consumer(myBlockingQuene).start();
}
}
线程1和线程2交替打印数字,本质上就是生产者和消费者模型,线程1生产5个数字,然后通知线程2生产5个数字,直到这个数字到达100
线程2打印:1
线程2打印:2
线程2打印:3
线程2打印:4
线程1打印:5
线程1打印:6
线程1打印:7
线程1打印:8
线程2打印:9
线程2打印:10
线程2打印:11
线程2打印:12
线程1打印:13
线程1打印:14
线程1打印:15
线程1打印:16
线程2打印:17
线程2打印:18
线程2打印:19
线程2打印:20
线程1打印:21
线程1打印:22
线程1打印:23
线程1打印:24
线程2打印:25
线程2打印:26
线程2打印:27
线程2打印:28
线程1打印:29
线程1打印:30
线程1打印:31
线程1打印:32
线程2打印:33
线程2打印:34
线程2打印:35
线程2打印:36
线程1打印:37
线程1打印:38
线程1打印:39
线程1打印:40
线程2打印:41
线程2打印:42
线程2打印:43
线程2打印:44
线程1打印:45
线程1打印:46
线程1打印:47
线程1打印:48
线程2打印:49
线程2打印:50
线程2打印:51
线程2打印:52
线程1打印:53
线程1打印:54
线程1打印:55
线程1打印:56
线程2打印:57
线程2打印:58
线程2打印:59
线程2打印:60
线程1打印:61
线程1打印:62
线程1打印:63
线程1打印:64
线程2打印:65
线程2打印:66
线程2打印:67
线程2打印:68
线程1打印:69
线程1打印:70
线程1打印:71
线程1打印:72
线程2打印:73
线程2打印:74
线程2打印:75
线程2打印:76
线程1打印:77
线程1打印:78
线程1打印:79
线程1打印:80
线程2打印:81
线程2打印:82
线程2打印:83
线程2打印:84
线程1打印:85
线程1打印:86
线程1打印:87
线程1打印:88
线程2打印:89
线程2打印:90
线程2打印:91
线程2打印:92
线程1打印:93
线程1打印:94
线程1打印:95
线程1打印:96
线程2打印:97
线程2打印:98
线程2打印:99
线程2打印:100
Process finished with exit code 0