首先要思考一个问题:为什么要使用这种模式进行生产代码。
优点:
极大的解决了代码之间的耦合程度
解释:
之前我们写的代码可能是这样的,有A和B 两个功能代码处理数据,B代码的执行必须要依赖于A代码才能执行完B的功能,即A耦合于B。显然这严重影响B代码的生产,而且如果产生错误的话,也不容易及时的排查。采用生产者消费者模式,A代码将处理好的数据交给缓存区,B代码直接从缓存区拿取数据进行处理,这样就把A与B的依赖关系给简介的消除了。
举个例子:
1、有3个面包师傅,每个师傅每10秒钟生产一个面包
2、并将面包放入到一个可以盛20个面包的篮子里,有5个吃面包的消费者,每每10秒钟从篮子里拿出一个面包吃掉,请设计并实现这个模型。
实现说明:
通过 wait,notify,notifyAll 实现消费者生产者,要注意原子性 synchronized
import java.util.ArrayList;
public class mainOffer {
public static void main(String[] args) {
stock stock = new stock();
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
stock.putOne(String.valueOf(Math.random()));
}
}
}, "面包师傅 " + i).start();
}
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
stock.getOne();
}
}
}, "吃瓜群众 " + i).start();
}
}
static class stock {
/**
* 最大的容量通知消费者
*/
private int maxMum = 20;
/**
* 最小的容量通知生产者
*/
private int minMum = 0;
/**
* 存储的列表
*/
private ArrayList<String> contain = new ArrayList<>();
/**
* 向里面放入东西
*
* @param name
*/
public synchronized void putOne(String name) {
//如果仓库中的容量大于最大容量进行线程等待
try {
Thread.sleep(1000L * 2);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (contain.size() > maxMum) {
try {
//线程等待
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//定义仓库中存在的内容
contain.add(name);
System.out.println(" 生产者 "
+ Thread.currentThread().getName()
+ " 生产了 " + name
+ " ,当前还剩:"
+ contain.size());
//唤起所有线程
this.notifyAll();
}
/**
* 向里面放入东西
*/
public synchronized void getOne() {
//如果仓库没有低于最低容量
while (contain.size() <= minMum) {
try {
//线程等待 等待生产者生产
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String temp = contain.get(0);
contain.remove(0);
System.out.println(" 消费者 "
+ Thread.currentThread().getName()
+ " 消费了 " + temp
+ " ,当前还剩:"
+ contain.size());
//唤起所有线程
this.notifyAll();
}
}
}