🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 多Product多Consumer之间的通讯导致出现程序假死的原因分析 继续上篇文章,我们来吧单个生产者消费者改成多个生产者消费者,这里使用java8的Stream,代码如下: ```java /** * @program: ThreadDemo * @description: 线程通信(生产者-消费者) * @author: hs96.cn@Gmail.com * @create: 2020-09-06 */ public class ProduceConsumerVersion2 { private int i = 0; private final Object LOCK = new Object(); /** * 是否已经消费 */ private volatile boolean isProduced = false; public void produce() { synchronized (LOCK) { if (isProduced) { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println("P->" + (++i)); LOCK.notify(); isProduced = true; } } } public void consume() { synchronized (LOCK) { if (isProduced) { System.out.println("C->" + i); LOCK.notify(); isProduced = false; } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { ProduceConsumerVersion2 pc = new ProduceConsumerVersion2(); // 多个生产者、消费者线程运行时,会产生一些问题 Stream.of("P1", "P2").forEach(n -> new Thread(() -> { while (true) { pc.produce(); } }, n).start() ); Stream.of("C1", "C2").forEach(n -> new Thread(() -> { while (true) { pc.consume(); } }, n).start() ); } } ``` 运行效果如下: ![](https://img.kancloud.cn/90/c5/90c5a2301ddff7bec48b437b1fc155ce_960x231.gif) 可以看到阻塞了,那么是不是有死锁了呢,jstack来查一下: ![](https://img.kancloud.cn/94/90/9490ebdde365cc00325da4a49425e6e6_960x231.gif) 可以看到没有死锁,那是为什么会卡住呢?下面增加一些调试语句用来定位跟踪,我把代码贴出来,有兴趣的朋友在大脑里分析一下,本地再执行一下验证自己的想法,代码如下: ```java public class ProduceConsumerVersion2 { private int i = 0; private final Object LOCK = new Object(); /** * 是否已经消费 */ private volatile boolean isProduced = false; public void produce() { synchronized (LOCK) { if (isProduced) { try { System.out.println(Thread.currentThread().getName() + "wait了"); LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { i++; System.out.println(Thread.currentThread().getName() + "生产了->" + i); LOCK.notify(); System.out.println(Thread.currentThread().getName() + "notify了" + i); isProduced = true; } } } public void consume() { synchronized (LOCK) { if (isProduced) { System.out.println(Thread.currentThread().getName() + "消费了->" + i); LOCK.notify(); System.out.println(Thread.currentThread().getName() + "notify了"); isProduced = false; } else { try { System.out.println(Thread.currentThread().getName() + "wait了"); LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { ProduceConsumerVersion2 pc = new ProduceConsumerVersion2(); // 多个生产者、消费者线程运行时,会产生一些问题 Stream.of("P1", "P2").forEach(n -> new Thread(() -> { while (true) { pc.produce(); } }, n).start() ); Stream.of("C1", "C2").forEach(n -> new Thread(() -> { while (true) { pc.consume(); } }, n).start() ); } } ``` 运行效果如下: ![](https://img.kancloud.cn/df/e6/dfe6c46c69028ee59918bb77be4ad3e7_1029x276.gif) 可以看到P1,C1,P2,C2都wait了,然后程序就假死了,这是什么原因呢? 这里我就不一步一步分析了,这里只需要明白一个道理即可,当有多个wait的时候,notify是随机的。这个我们后续再探讨,先吃个饭~