生产者和消费者模型
- 生产线程负责生产,消费线程负责消费
- 生产和消费要达到平衡
这是一种特殊的业务需求,在这种特殊情况下需要使用基于线程共享对象的wait和notify方法
- wait和notify是普通java对象的方法,而不是Runnable实例对象和Thread对象的方法
- wait和notify方法都建立在synchronized,因为多线程操作同一个共享对象,存在线程安全问题
模型假设:
- 假设有一个容量为1的List仓库被一个生产者线程和一个消费者线程共享
- 生产者不断生产,每次生产一个放到仓库中
- 消费者不断消费,每次从仓库中取出后消费一个
- 仓库满的话生产者停止生产,仓库空了的话消费者停止消费
模型示意图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020083023372020.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTU3MTg2,size_16,color_FFFFFF,t_70#pic_center)
模型流程图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200830233738464.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTU3MTg2,size_16,color_FFFFFF,t_70#pic_center)
实现:
主线程:
import java.util.ArrayList;
import java.util.List;
public class ProducerAndConsumer {
public static void main(String[] args) {
List list = new ArrayList();
Thread proThread = new Thread(new Producer(list));
Thread conThread = new Thread(new Consumer(list));
proThread.setName("生产线程");
conThread.setName("消费线程");
proThread.start();
conThread.start();
}
}
生产者线程:
class Producer extends Thread{
private List list;
public Producer(List list){
this.list = list;
}
@Override
public void run() {
while(true){
synchronized (list){
if (list.size()>0){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object product = new Object();
list.add(product);
System.out.println(Thread.currentThread().getName()+" 生产了:一个产品"+product);
list.notify();
}
}
}
}
消费者线程:
class Consumer extends Thread{
private List list;
public Consumer(List list){
this.list = list;
}
@Override
public void run() {
while(true){
synchronized (list){
if (list.size()==0){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object product = list.remove(0);
System.out.println(Thread.currentThread().getName()+" 消费了:一个产品"+product);
list.notify();
}
}
}
}
执行结果:
生产线程 生产了:一个产品java.lang.Object@2ea567fa
消费线程 消费了:一个产品java.lang.Object@2ea567fa
生产线程 生产了:一个产品java.lang.Object@2d36607d
消费线程 消费了:一个产品java.lang.Object@2d36607d
生产线程 生产了:一个产品java.lang.Object@26e6a4a8
消费线程 消费了:一个产品java.lang.Object@26e6a4a8
生产线程 生产了:一个产品java.lang.Object@16be2ec1
消费线程 消费了:一个产品java.lang.Object@16be2ec1
...
...
生产线程 生产了:一个产品java.lang.Object@13a1115b
消费线程 消费了:一个产品java.lang.Object@13a1115b
生产线程 生产了:一个产品java.lang.Object@d0aaeda
消费线程 消费了:一个产品java.lang.Object@d0aaeda
生产线程 生产了:一个产品java.lang.Object@1eda9837
消费线程 消费了:一个产品java.lang.Object@1eda9837
生产线程 生产了:一个产品java.lang.Object@7975650b
消费线程 消费了:一个产品java.lang.Object@7975650b
...