线程通信之两种常用生产者消费者模式
一、传统的生产者消费者模式
传统的生产者消费者模式一般是采用Synchronized或者Lock锁来实现的。
/**
多线程编程模式
1、高聚低合前提下,线程操作资源类
2、判断/干活/通知
3、防止虚假唤醒
**/
class A {
private int nums = 0;
public synchronized void increment() throws InterruptedException {
//等待条件
while (nums != 0) {
//等待
this.wait();
}
nums++;
System.out.println(Thread.currentThread().getName() + "->=" + nums);
//通知其它线程,我+1完成了
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//等待条件
while (nums == 0) {
//等待
this.wait();
}
nums--;
System.out.println(Thread.currentThread().getName() + "->=" + nums);
//通知其它线程,我-1完成了
this.notifyAll();
}
}
public class Test2 {
public static void main(String[] args) {
A a = new A();
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
a.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
a.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "B").start();
}
}
二、阻塞队列实现的生产者消费者模式
以ArrayBlockingQueue为例
public class ProductCustomer_BlockingQueue {
public static void main(String[] args) {
Cate cate = new Cate(new ArrayBlockingQueue<>(10));
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "生产线程启动");
try {
cate.prod();
} catch (Exception e) {
e.printStackTrace();
}
}, "Prod").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "消费线程启动");
try {
cate.consume();
} catch (Exception e) {
e.printStackTrace();
}
}, "Consume").start();
//只允许生产消费5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
cate.stop();
}
}
class Cate {
//volatile保证变量可见性
private volatile boolean FLAG = true; //信号量,默认是true
private BlockingQueue<String> blockingQueue = null;
//使用原子类保证++操作的原子性
private AtomicInteger atomicInteger = new AtomicInteger();
//接受对应的实现类
public Cate(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
//生产
public void prod() throws Exception {
String data = null;
while (FLAG) {
data = atomicInteger.incrementAndGet() + "";
boolean offer = blockingQueue.offer(data, 2l, TimeUnit.SECONDS);
if (offer) {
System.out.println(Thread.currentThread().getName() + "插入队列成功" + data);
} else {
System.out.println(Thread.currentThread().getName() + "插入队列失败");
}
TimeUnit.SECONDS.sleep(1);
}
//
System.out.println(Thread.currentThread().getName() + "下班了,FLAG = false");
}
//消费
public void consume() throws Exception {
String result = null;
while (FLAG) {
result = blockingQueue.poll(2l, TimeUnit.SECONDS);
if (Objects.isNull(result) || result.equals("")) {
FLAG = false;
System.out.println(Thread.currentThread().getName() + "超过2秒没有取到蛋糕,消费结束");
System.out.println();
System.out.println();
return;
}
System.out.println(Thread.currentThread().getName() + "消费成功" + result);
}
}
//停止
public void stop() {
this.FLAG = false;
}
}