目录
生产者-消费者模式是并发编程中的一个经典的问题
生产者-消费者问题描述:
1.生产者和消费者在同一时间段内共用同一个存储空间;
2.生产者往存储空间中添加产品,消费者从存储空间中取走产品;
3.当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
java中解决该问题的办法有三个:
1.sync,wait,notify
2.lock,await,singal
3.阻塞队列实现
本文从阻塞队列的方面介绍该问题,话不多说,上代码
资源类:
package test;
import org.springframework.util.StringUtils;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Resource {
//该标记变量标记是否开启 “生产-消费”模式,true表示开启,false表示关闭
private volatile boolean flag = true;
//定义变量去计算 生产-消费 物品的个数 需要保证原子性,所以使用该类型变量
private AtomicInteger atomicInteger = new AtomicInteger();
//定义阻塞队列 以构造方法传入具体的队列形式
BlockingQueue<String> blockingQueue = null;
public Resource(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println("***传入的阻塞队列是:" + blockingQueue.getClass().getName());
}
//定义生产方法
public void myProd() throws Exception {
String data = null;
boolean retValue;
while (flag) {
data = atomicInteger.incrementAndGet() + "";
retValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if (retValue) {
System.out.println(Thread.currentThread().getName() + "\t" + "插入队列" + data + "成功");
} else {
System.out.println(Thread.currentThread().getName() + "\t" + "插入队列" + data + "失败");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName() + "\t" + "生产动作结束");
}
//定义消费方法
public void myConsume() throws Exception {
String result = null;
while (flag) {
result = blockingQueue.poll(2L, TimeUnit.SECONDS);
//说明取出失败,超时之后将退出生产-消费模式
if (StringUtils.isEmpty(result)) {
flag = false;
System.out.println(Thread.currentThread().getName() + "\t" + "超过2s没有取到,退出");
System.out.println();
System.out.println();
return;
}
System.out.println(Thread.currentThread().getName() + "\t" + "消费" + result + "成功");
TimeUnit.SECONDS.sleep(2);
}
}
public void stop() throws Exception {
this.flag = false;
}
}
测试类
package test;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 使用阻塞队列模拟 生产者-消费者 模式
* 生产者-消费者问题描述:
* 1.生产者和消费者在同一时间段内共用同一个存储空间;
* 2.生产者往存储空间中添加产品,消费者从存储空间中取走产品;
* 3.当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
* 程序业务描述:
* 1.生产者有序生产,消费者有序消费
* 2.可以通过变量控制该模式启动或者停止
* 3.生产者产能不足,消费者消费物品时,如果从队列里取不到物品,等待2s,超时则退出该模式
* 4.生产者生产太多,消费者消费不完,生产者阻塞。
* 5.库房内存为10
*/
public class Main {
public static void main(String[] args) throws Exception {
//new 一个数组阻塞队列,初始化10
Resource resource = new Resource(new ArrayBlockingQueue<>(10));
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + "生产线程启动");
try {
resource.myProd();
} catch (Exception e) {
e.printStackTrace();
}
}, "A线程").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + "消费线程启动");
System.out.println();
System.out.println();
try {
resource.myConsume();
} catch (Exception e) {
e.printStackTrace();
}
}, "B线程").start();
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.stop();
System.out.println("5s时间到,生产-消费模式退出");
}
}
运行结果展示:
1.生产者有序生产,消费者有序消费
2.可以通过变量控制该模式启动或者停止
3.生产者产能不足,消费者消费物品时,如果从队列里取不到物品,等待2s,超时则退出该模式
4.通过变量控制该模式停止之后,生产结束,消费者未取到物品,等待2s,超时则退出该模式
4.生产者生产太多,消费者消费不完,生产者阻塞。
注:要想模拟上述所有情况,需要修改某些变量的值,例如库存的数值,生产线程生产物品之后休眠的时间,消费线程消费物品之后休眠的时间