#30天专注成长计划#day 16 java 多线程设计模式-生产者消费者模式

1.什么是生产者消费者模式?###

生产者-消费者模式是一个经典的多线程设计模式。它为多线程间的协作提供了良好的解决方案。 在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程。生产者线 程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务。生产者和消费者之间则通 过共享内存缓冲区进行通信

2.生产者消费者模式图解

Paste_Image.png

单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据

3.她有三个特点

解耦

假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。

◇支持并发(concurrency)

生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只好一直等在那边。万一消费者处理数据很慢,生产者就会白白糟蹋大好时光。   使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种,后面的帖子会讲两种并发类型下的应用)。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。其实当初这个模式,主要就是用来处理并发问题的。

◇支持忙闲不均

缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。
有时候要根绝具体情况,如果想要,并发量很大,很可能是不需要阻塞队列的,这个时候就需要重新设计了,ConcurrentLinkedQueue.效率会比阻塞队列高一些。

4.最简单的代码实现部分。

public class ShengChanXiaoFei {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        BlockingQueue<String> queue = new LinkedBlockingQueue<String>();

        Procedure p = new Procedure(queue);

        Customer c = new Customer(queue);
        service.execute(p);
        service.execute(c);

    }

}
//生产者
class Procedure implements Runnable {

    public BlockingQueue<String> queue;

    public Procedure(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            queue.offer("teste" + System.currentTimeMillis());

            System.err.println("放数据:teste" + System.currentTimeMillis());
        }
    }
}

//消费者
class Customer implements Runnable {
    public BlockingQueue<String> queue;//缓冲区队列

    public Customer(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            String value;
            try {
                Thread.sleep(1000);
                value = queue.take();
                System.err.println("取数据:" + value);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
```
####测试结果
 
 
 
![test.png](http://upload-images.jianshu.io/upload_images/2510853-7f7cebe7b2301ae9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###代码自此玩
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 简介 在实际的软件开发过程中,经常会碰到如下场景: 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模...
    RadioWaves阅读 11,475评论 2 16
  • 又是一个有人欢喜有人哭的节日。 比如,她在笑,我在哭,你在笑。 远处的烟花灿烂,远处的男女缠绵,你发微博还艾特我说...
    安婩阅读 2,271评论 0 0
  • 什么东西需要长期保存的? 衣服,书籍,日用品,纪念品。有时真想把所有的东西都照成照片,可是又不太现实。
    我心我愿秀阅读 3,762评论 0 1
  • 打动我的地方: 1.人不为己天诛地灭,当我们作为人不成为我们自己的时候,连老天爷都看不下去了 2.走大运的人,先成...
    luluandxiaoma阅读 3,211评论 0 1

友情链接更多精彩内容