异步模式之生产者/消费者

黑马视频教程:https://www.bilibili.com/video/BV16J411h7Rd?p=107

1.定义

  • 消费队列可以用来平衡生产和消费之间的平衡
  • 生产者仅负责产生结果的数据,不关心数据如何处理,而消费者专心处理数据的结果
  • 消息队列容量有限为空消费者无法消费,满时生产者无法生产。
  • JDK中的各种阻塞队列采用的就是这种模式。

在这里插入图片描述

2.实现

代码注释详细

/**
 * 消息类
 */
@Slf4j
class Message{

    private int id;
    private Object message;

    public Message(int id,Object message){
        this.id = id;
        this.message = message;
    }

    public int getId() {
        return id;
    }

    public Object getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "Message{" +
                "id=" + id +
                ", message=" + message +
                '}';
    }


}

/**
 * 消息队列
 */
@Slf4j
class MessageQueue{

    /**
     * 存放消息的队列
     */
    private LinkedList<Message> queue;
    /**
     * 消息队列的容量大小
     */
    private Integer capacity;

    public MessageQueue(Integer capacity) {
        this.capacity = capacity;
        queue = new LinkedList<>();
    }

    /**
     * put消息message到消息队列中
     * @param message
     */
    public void put(Message message){
        synchronized (queue){
            // 队列已满就继续等待
            while (capacity.equals(queue.size())){
                try {
                    log.debug("消息队列满了,无法继续添加消息到队列中");
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            log.debug("添加消息{}到消息队列中",message);
            queue.addLast(message);
            // 唤醒队列为空情况下等待的调用take方法的线程
            queue.notifyAll();
        }
    }

    /**
     * 消费消息
     * @return
     */
    public Message take(){
        synchronized (queue){
            // 队列为空没有消息,等待生产者生产消息到消费队列中
            while (queue.size() == 0){
                try {
                    log.debug("消息队列为空,无法消费,继续等待");
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Message message = queue.removeFirst();
            log.debug("消费消息{}",message);
            // 唤醒因队列为满的情况下调用put方法等待的线程
            queue.notifyAll();
            return message;
        }
    }

}

3.测试

测试代码

	/**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        MessageQueue messageQueue = new MessageQueue(2);

        // 模拟三个生产者
        for (int i = 0; i < 3; i++) {
            int id = i;
            new Thread(()->{
                messageQueue.put(new Message(id,"消息" +id));
            },"生产者线程 t"+i).start();
        }

        // 一个消费者
        new Thread(()->{
            while (true){
                log.debug("1s后消费");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message take = messageQueue.take();
            }
        },"消费者线程 t1").start();
    }

测试结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值