定义
与前面的保护性暂停中的 GuardObject 不同,不需要产生结果和消费结果的线程一一对应
消费队列可以用来平衡生产和消费的线程资源
生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据
消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据
JDK 中各种阻塞队列,采用的就是这种模式
有点类似MQ的模式,这个直接写代码吧。重复消费等乱七八糟的现象就不考虑了。
package com.bo.threadstudy.four;
import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
/**
* 生产者消费者模式
*/
@Slf4j
public class ProducerConsumerTest {
public static void main(String[] args) {
Factory<Integer> factory = new Factory<>(10);
for (int i = 0; i < 4; i++) {
new Thread(() -> {
while(true){
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
factory.produce(factory.getCurSize());
}
},"p"+i).start();
}
for (int i = 0; i < 2; i++) {
new Thread(() -> {
while(true){
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
factory.consume();
}
},"c"+i).start();
}
}
}
@Slf4j
class Factory<T>{
private LinkedList<T> list = new LinkedList();
private int size = 0;
//设置长度
public Factory(int size) {
this.size = size;
}
public int getCurSize(){
return list.size();
}
//消费
public void consume(){
synchronized (this){
//size = 0的时候,阻塞不动
while(list.size()<=0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = list.removeFirst();
log.debug("当前元素消费:"+t);
//唤醒所有线程,可以消费,也可以生产
this.notifyAll();
}
}
//生产
public void produce(T t){
synchronized (this){
//size = 0的时候,阻塞不动
while(list.size() >= size){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.addFirst(t);
log.debug("当前元素生产:"+t);
//唤醒所有线程,可以消费,也可以生产
this.notifyAll();
}
}
}
随手写一个,没什么难度,这里虚假唤醒 等场景都考虑到了。没什么意思。