定义:
要点:
- 消费队列可以用来平衡生产喝消费线程资源
- 生产者仅负责产生结果数据,不关心数据该如何处理,而消费者转型处理结果数据
- 消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据
- JDK中各种阻塞队列,采用的就是这种模式
实现
## 队列实现类
@Slf4j
class MessageQueue {
//容器
private LinkedList<Message> list = new LinkedList<>();
//容器容量
private int capcity;
public MessageQueue(int capcity) {
this.capcity = capcity;
}
/**
* 获取消息
*
* @return
*/
public Message take() {
//检查队列是否为空
synchronized (list) {
while (list.isEmpty()) {
try {
log.debug("队列为空,消费者线程等待.....");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Message message = list.removeFirst();
log.debug("已消费了消息{}", message);
list.notifyAll();
return message;
}
}
/**
* 存入消息
*
* @param message
*/
public void put(Message message) {
synchronized (list) {
//检查队列是否已满
while (list.size() == capcity) {
try {
log.debug("队列已满,生产者线程等待....");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.addLast(message);
log.debug("已生产消息{}", message);
list.notifyAll();
}
}
}
## 消息类
@Data
@AllArgsConstructor
@ToString
final class Message {
private int id;
private Object value;
}
## 测试类
public class Test {
public static void main(String[] args) {
MessageQueue queue = new MessageQueue(2);
for (int i = 0; i < 3; i++) {
int id = i;
new Thread(() ->
queue.put(new Message(id, "消息>>>" + id))
, "生产者" + i).start();
}
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message take = queue.take();
}
}, "消费者").start();
}
}
结果:
从结果中可以看出,生产者生产的每条消息都会被不同的消费者进行消费,不会固定的线程进行消费,每当容器满时将会等待消费者进行消费后才会继续生产消息,而消息被消费完后将会等待生产者继续生产消息后再继续进行消费。