橙子学院-30天专注橙长计划

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

2016-09-21  本文已影响116人  G先生_海林

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](https://img.haomeiwen.com/i2510853/7f7cebe7b2301ae9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###代码自此玩
上一篇下一篇

猜你喜欢

热点阅读