继续上篇文章,我们来吧单个生产者消费者改成多个生产者消费者,这里使用java8的Stream,代码如下:
/**
* @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()
);
}
}
运行效果如下:
可以看到阻塞了,那么是不是有死锁了呢,jstack来查一下:
可以看到没有死锁,那是为什么会卡住呢?下面增加一些调试语句用来定位跟踪,我把代码贴出来,有兴趣的朋友在大脑里分析一下,本地再执行一下验证自己的想法,代码如下:
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()
);
}
}
运行效果如下:
可以看到P1,C1,P2,C2都wait了,然后程序就假死了,这是什么原因呢?
这里我就不一步一步分析了,这里只需要明白一个道理即可,当有多个wait的时候,notify是随机的。这个我们后续再探讨,先吃个饭~
多Product多Consumer之间的通讯导致出现程序假死的原因分析
原文:https://www.cnblogs.com/stormsquirrel/p/13623274.html