生产者消费者模型:
生产者生产后 通知 正在 等待 的消费之消费 线程通信
**注意:**判断时不能使用if()否则将 出现 虚假唤醒 的情况<线程越多错误越明显> 应使用while()判断 因为if判断只判断一次且执行时不会停止导致同时判断到num=1或者0 结果出现错误 所有等待应出现在循环中
用if判断的话,唤醒后线程会从wait之后的代码开始运行,但是不会重新判断if条件,直接继续运行if代码块之后的代码,而如果使用while的话,也会从wait之后的代码运行,但是唤醒后会重新判断循环条件,如果不成立再执行while代码块之后的代码块,成立的话继续wait。
这也就是为什么用while而不用if的原因了,因为线程被唤醒后,执行开始的地方是wait之后。
synchronized实现:
等待this.wait();
,业务,通知this.notifyAll();
/**
* synchronized方式实现生产者消费者模型
*/
public class PcSynTest01 {
/**
* 主线程 模拟多线程操作
*/
public static void main(String[] args) {
//获取同一资源
MyData myData = new MyData();
//多线程执行
new Thread(()->{
for (int i = 0; i < 6; i++) myData.increment();},"A >").start();
new Thread(()->{
for (int i = 0; i < 6; i++) myData.decrement();},"B >").start();
new Thread(()->{
for (int i = 0; i < 6; i++) myData.increment();},"C >").start();
new Thread(()->{
for (int i = 0; i < 6; i++) myData.decrement();},"D >").start();
}
}
/**
* 同一个实体
*/
class MyData{
/**
* 被生产或消费的具体东西
*/
private Integer num = 0;
/**
* 生产方法
*/
public synchronized void increment(){
//判断是否有具体的 东西 如果有则等待其他线程消费后当num=0时在去生产
//注意:判断时不能使用if()否则将 出现虚假唤醒的情况
while (num != 0){
//即:当有num时 等待
try {
this.wait();//使调用此方法的线程 等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断当没有 具体东西时则生产 生产后通知其他线程消费
while (num == 0){
num++;
System.out.println(Thread.currentThread().