生产者消费者模式

生产者消费者问题

(概念摘自:百度百科)



     生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。


解决办法:


使用多线程阻塞实现消息队列



消息队列的应用场景

消息队列的主要特点是异步处理,主要目的是减少请求响应时间和解耦。所以主要的使用场景就是将比较耗时而且不需要即时(同步)返回结果的操作作为消息放入消息队列。同时由于使用了消息队列,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要受对方的影响,即解耦和。



使用线程阻塞简单实现消息队列


需要用到的两个方法:

 void wait()  //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
 void notifyAll() //唤醒在此对象监视器上等待的所有线程。


创建消息队列Queue.java
package com.lingdu.thread;

import java.util.LinkedList;

/**
 * 消息队列
 * 生产者与消费者的关系
 * @author LingDu
 */
public class Queue {
    //创建一个链表
    private LinkedList<String> queue = new LinkedList<String>();
    //设置最大长度为10
    private int maxSize = 10;
    //创建一个对象锁
    private static final Object lock = new Object();

    public Queue(int maxSize) {
        super();
        this.maxSize = maxSize;
    }



    /**
     * 用于存入消息
     * @param msg
     */
    public  void pushMessage(String msg) {
        synchronized (lock) {
            // wait必须是在while循环里面
            //大于最大值时则进入等待
            while (queue.size() >= maxSize) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.push(msg);
            // 唤醒所有
            lock.notifyAll();
        }

    }

    /**
     * 用于取出消息
     * @return
     */
    public  String getMessage() {
        synchronized (lock) {
            //链表大小小于1则进入等待
            while (queue.size() < 1) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //唤醒所有
            lock.notifyAll();
            //弹出消息
            return queue.pop();
        }

    }
}


生产者ProducerTask
package com.lingdu.thread;

/**
 * 生产者
 * @author LingDu
 */
public class ProducerTask implements Runnable {
    private Queue queue;

    public ProducerTask(Queue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        /**
         * 每次产生30个消息
         */
        for (int i = 1; i <= 30; i++) {
            queue.pushMessage("msg:" + i);
        }
    }
}


消费者ConsumerTask
package com.lingdu.thread;

/**
 * 消费者
 * @author LingDu
 */
public class ConsumerTask implements Runnable {
    private Queue queue;

    public ConsumerTask(Queue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        /**
         * 每次处理10个消息
         */
        for (int i = 0; i < 10; i++) {
            String msg = this.queue.getMessage();
            System.out.println(msg);
        }
    }
}


测试类Test.java
package com.lingdu.thread;

public class Test {

    public static void main(String[] args) {
        //创建链表对象并且初始化长度为10
        Queue queue = new Queue(10);
        //生产者对象
        ProducerTask pro = new ProducerTask(queue);
        //消费者对象
        ConsumerTask con = new ConsumerTask(queue);
        //产生消息
        new Thread(pro).start();
        //开启3个消费者同时取消息
        new Thread(con).start();
        new Thread(con).start();
        new Thread(con).start();
    }

}

2



使用消息队列的好处:

https://www.oschina.net/translate/top-10-uses-for-message-queue



最后这里介绍两个消息中间件Notify和MetaQ

  • 消息系统的核心作用就是三点:解耦,异步和并行

有兴趣的小伙伴可以去看看

http://www.tuicool.com/articles/zqyYrm

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值