使用BlockingQueue的生产者消费者Demo
一个生产者消费者的Demo,不要再用synchronized或者lock了,那只是帮助你了解原理,生产大部分还是用的BlockingQueue队列。其实底层也是用ReentrantLock加的锁。
生产者消费者模型是什么?
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列BlockingQueue作为一个缓存区来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者索要数据,而是直接从阻塞队列里取,阻塞队列起到缓冲作用,使生产者消费者达到动态平衡。
一句话概括?
生产者进行数据生产,缓存区如果达到最大值,生产者进程被阻塞;
消费者进行数据消费,缓存区如果为空,消费者进程被阻塞。
生产者消费者的模型作用?
通过BlockingQueue作为缓存区,达到去中心化、降低耦合度的目的。并且支持并发,可以解决忙闲不均的问题。
实现代码如下:
package com.solid.demo.blockQueueTest;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class BlockQueueTest {
public static void main(String[] args) {
ResourceTest resource = new ResourceTest(new ArrayBlockingQueue<Integer>(3));
new Thread(()->{
System.out.println("线程A开始生产");
resource.production();
}, "A").start();
new Thread(()->{
System.out.println("线程B开始消费");
resource.consumption();
}, "B").start();
new Thread(()->{
System.out.println("线程C开始生产");
resource.production();
}, "C").start();
new Thread(()->{
System.out.println("线程D开始消费");
resource.consumption();
}, "D").start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
resource.stop();
}
}
}
class ResourceTest{
private volatile Boolean FLAG = true;
private final AtomicInteger atomicInteger = new AtomicInteger();
private BlockingQueue<Integer> blockingQueue = null;
public ResourceTest(BlockingQueue<Integer> blockingQueue){
this.blockingQueue = blockingQueue;
}
public void production(){
try {
boolean offer;
while (FLAG) {
offer = blockingQueue.offer(atomicInteger.incrementAndGet(), 2, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + "\t生产"+(offer?"成功":"失败"));
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consumption(){
try {
Integer poll;
while (FLAG) {
poll = blockingQueue.poll(2, TimeUnit.SECONDS);
if (poll == null){
FLAG = false;
System.out.println(Thread.currentThread().getName() + "\t 消费失败,退出当前队列!");
}else {
System.out.println(Thread.currentThread().getName() + "\t 消费" + poll + "成功");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void stop(){
this.FLAG = false;
}
}