异步模式生产者消费者模式
4.1要点
保护性暂停中的GuardedObject适合一一对应,而大多数时候不需要生产者和消费者是一一对应的
可以使用消息队列来平衡生产者和消费者的线程资源
生产者只负责对资源的生产,消费者只专注于处理结果
消息队列有容量限制,满时不添加,空时不消耗
JDK中的各种阻塞队列都是采用这个模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NPuBTycZ-1655015868708)(F:\Java_note\java笔记\img\生产者消费者示意图.png)]
4.2实现
package com.zjc.study.day612;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
import java.util.List;
/**
* 生产者消费者模式
*/
public class Ops1 {
public static void main(String[] args) {
//定义消息队列 传入消息队列容量
MeaageQueue meaageQueue = new MeaageQueue(3);
new Thread(()->{
for (int j = 0; j < 6; j++) {
meaageQueue.put(new Message(j,"message:"+j));
}
}).start();
new Thread(()->{
for (int j = 0; j < 2; j++) {
meaageQueue.getMessage();
}
}).start();
}
}
/**
* 创建消息类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
class Message {
private int id;
private Object message;
}
/**
* 创建消息队列
* 其中应该包含产生和消费
*/
@Slf4j
class MeaageQueue {
//定义
private LinkedList<Message> list = new LinkedList<>();
//定义容量
private int capacity;
//定义有参构造传入容量
public MeaageQueue(int capacity) {
this.capacity = capacity;
}
/**
* 定义生产方法
* 生产方法需要看消息队列是否已满
* 1.不满 生产
* 2.满 等待
*
* @param message
*/
public void put(Message message) {
//多线程操作需要加锁
synchronized (list) {
//如果消息队列已满,生产者线程不用生产
while (list.size() == capacity) {
try {
log.info("消息队列已满,生产者线程不用生产:{}",list.size());
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//不满则加
list.addLast(message);
log.info("消息添加成功:{}",message);
//要记住唤醒已经wait的线程
list.notifyAll();
}
}
/**
* 定义消费方法
* 消费时需要判断消息队列是否为空
* 1.不为空 消费
* 2.为空 等待
*
* @return
*/
public Message getMessage() {
//如果list为空消费者线程不能消费
synchronized (list) {
while (list.isEmpty()) {
try {
log.info("消息队列为空,消费者线程不能消费");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//取出最先生产的
Message message = list.removeFirst();
log.info("消息消费成功:{}",message);
//唤醒生产线程
list.notifyAll();
return message;
}
}
}