使用notifyAll完善多线程下的生产者消费者模型
使用notifyAll完善多线程下的生产者消费者模型
我们先看一下wait()的代码注释:

使当前线程等待,直到另一个线程调用了这个对象的notify()或notifyAll()方法,换句话说,这个方法是执行了wait(0);
当前线程必须拥有该对象的监视器。线程释放此监视器的所有权,并等待另一个线程通过调用notify()或notifyAll()方法,让这个对象监视器上等待的线程被唤醒,然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。
notify()是通知一个线程唤醒,而notifyAll()是会将wait()在同一个monitor的所有线程都会唤醒,而我们之前出现问题就是因为notify是随机的,那么我们现在使用notifyAll试一下:
/**
* @program: ThreadDemo
* @description: 优化多线程下的生产者消费者模型,避免多生产者-多消费者造成的程序假死
* @author: hs96.cn@Gmail.com
* @create: 2020-09-07
*/
public class ProduceConsumerVersion3 {
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();
}
}
System.out.println(Thread.currentThread().getName() + "->" + (++i));
LOCK.notifyAll();
isProduced = true;
}
}
public void consume() {
synchronized (LOCK) {
if (!isProduced) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "->" + i);
LOCK.notifyAll();
isProduced = false;
}
}
public static void main(String[] args) {
ProduceConsumerVersion3 pc = new ProduceConsumerVersion3();
Stream.of("P1", "P2", "P3").forEach(n -> new Thread(new Runnable() {
@Override
public void run() {
while (true) {
pc.produce();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, n).start());
Stream.of("C1", "C2", "C3", "C4").forEach(n -> new Thread(() -> {
while (true) {
pc.consume();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, n).start());
}
}
运行效果如下:

可以看到有连续生产2个的情况,那么是什么原因导致的呢?
其实仔细想一下,就是p3的生产完之后释放锁,然后p2抢到了,就继续生产了,那么怎么解决呢?让p2wait到p3生产的数据消费掉即可了,改进代码如下:‘
/**
* @program: ThreadDemo
* @description: 优化多线程下的生产者消费者模型,避免多生产者-多消费者造成的程序假死
* @author: hs96.cn@Gmail.com
* @create: 2020-09-07
*/
public class ProduceConsumerVersion3 {
private int i = 0;
private final Object LOCK = new Object();
private volatile boolean isProduced = false;
public void produce() {
synchronized (LOCK) {
while (isProduced) {
try {
//System.out.println(Thread.currentThread().getName()+"wait....");
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "->" + (++i));
LOCK.notifyAll();
isProduced = true;
}
}
public void consume() {
synchronized (LOCK) {
while (!isProduced) {
try {
//System.out.println(Thread.currentThread().getName()+"wait....");
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "->" + i);
LOCK.notifyAll();
isProduced = false;
}
}
public static void main(String[] args) {
ProduceConsumerVersion3 pc = new ProduceConsumerVersion3();
Stream.of("P1", "P2", "P3").forEach(n -> new Thread(new Runnable() {
@Override
public void run() {
while (true) {
pc.produce();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, n).start());
Stream.of("C1", "C2", "C3", "C4").forEach(n -> new Thread(() -> {
while (true) {
pc.consume();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, n).start());
}
}
运行效果如下:


浙公网安备 33010602011771号