Java的设计模式(7)— 生产者-消费者模式

  生产者-消费者模式是一个经典的多线程设计模式,它为多线程间的协作提供了良好的解决方案。这个模式中,通常有两类线程,即若干个生产者线程和若干个消费者线程。生产者线程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务。生产者和消费者之间通过共享内存缓存区进行通信,这样就避免了生产者和消费者直接通信,从而将生产者和消费者解耦。不管是生产高于消费,还是消费高于生产,缓存区的存在可以确保系统的正常运行。这个模式有以下几种角色:

  • 生产者:用于提交用户的请求,提取用户任务,装入内存缓冲区。
  • 消费者:在内存缓冲区中提取并处理任务。
  • 内存缓冲区:缓存生产者提交的任务或数据,供消费者使用。
  • 任务:生产者向内存缓冲区提交的数据结构。
  • Main:使用消费者和生产者的客户端。

  其中BlockingQueue充当了共享内存缓冲区,用于维护任务或数据队列(PCData对象)。PCData表示一个生产任务,或者相关任务的数据,生产者对象和消费者对象均引用一个BlockingQueue实例。生产者负责创建PCData对象,并将它加入队列中,消费者从这个队列中获取PCData对象。下面举个例子:

  首先生产者线程实现如下,它构建PCData对象,并放入BlockingQueue队列中

public class Producer implements Runnable {

    private volatile boolean isRunning = true;
    private BlockingQueue<PCData> queue;                        // 内存缓存区
    private static AtomicInteger count = new AtomicInteger();   // 总数,原子操作
    private static final int SLEEPTIME = 1000;

    public Producer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        PCData data = null;
        Random r = new Random();
        System.out.println("start producer id = "+Thread.currentThread().getId());
        try {
            while(isRunning){
                Thread.sleep(SLEEPTIME);
                data = new PCData(count.incrementAndGet());    // 构造任务数据
                System.out.println(data+" is put into queue");
                if(!queue.offer(data,2,TimeUnit.SECONDS)){     // 提交到数据缓存区中
                    System.out.println("failed to put data:"+data);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }

    public void stop(){
        isRunning = false;
    }
}

  对应的消费者实现如下,它从BlockingQueue队列中取出PCData对象,并进行相应的计算。

public class Consumer implements Runnable {

    private BlockingQueue<PCData> queue;
    private static final int SLEEPTIME = 1000;

    public Consumer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        System.out.println("start Consumer id = "+Thread.currentThread().getId());
        Random r = new Random();
        try {
        while(true){
            PCData data  =this.queue.take();
            if(null!=data){
                int re = data.getData() * data.getData();
                System.out.println(MessageFormat.format("{0}*{1}={2}", data.getData(),data.getData(),re));
                Thread.sleep(r.nextInt(SLEEPTIME));
            }
        }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
}

  PCData对象作为生产者和消费者之间的共享数据模型,定义如下:

public class PCData {

    private final int intData;
    public PCData(int d){
        intData = d;
    }
    public PCData(String d){
        intData = Integer.valueOf(d);
    }
    public int getData(){
        return intData;
    }
    @Override
    public String toString() {
        return "intData:" + intData;
    }

}

  在主函数中,创建三个生产者和三个消费者,并让他们协作运行,在主函数实现中,定义LinkedBlockingQueue作为BlockingQueue队列的实现类。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<PCData> queue = new LinkedBlockingQueue<PCData>();
        Producer p1 = new Producer(queue);
        Producer p2 = new Producer(queue);
        Producer p3 = new Producer(queue);
        Consumer c1 = new Consumer(queue);
        Consumer c2 = new Consumer(queue);
        Consumer c3 = new Consumer(queue);
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(p1);
        service.execute(p2);
        service.execute(p3);
        service.execute(c1);
        service.execute(c2);
        service.execute(c3);
        Thread.sleep(10000);
        p1.stop();
        p2.stop();
        p3.stop();
        Thread.sleep(3000);
        service.shutdown();
    }
}

  生产者-消费者模式很好地对生产者线程和消费者线程进行解耦,优化了系统整体结构。同时,由于缓冲作用,允许生产者和消费者线程存在执行上的性能差异,从一定程度上解决了性能瓶颈对系统性能的影响。

原文地址:https://www.cnblogs.com/wangyongwen/p/11332436.html

时间: 2024-10-23 14:35:38

Java的设计模式(7)— 生产者-消费者模式的相关文章

java设计模式之生产者/消费者模式

什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者.在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式.结构图如下: 生产者消费者模式有如下几个优点: 1.解耦   由于有缓冲区的存在,生产者和消费者之间不直接依赖,耦合度降低. 2.支持并发   由于生产者与消费

设计模式之生产者消费者模式

一丶背景 说到生产者消费者模式就要先提提多线程了,多线程开发是开发中所常用的,多线程程序相对于单线程程序稳定性更强, 一个线程挂了不会影响整个程序的正常运行.但是当多线程同时操作一个数据源的时候就会出现脏读. 二丶介绍生产者消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过 阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而 是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区

java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了  wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样,先定义一个缓冲区: public class ValueObject { public static String value = ""; } 换种写法,生产和消费方法放在一个类里面: public class ThreadDomain41 extends ReentrantLock {

生产者消费者模式的java实现(实现一)

在多线程以及并发工具类中,常用的一种思想就是生产者消费者模式,生产者负责生产物品,将物品放到传送带,消费者负责获取传送带的物品,消费物品.现在只考虑最简单的情况,传送带上只允许放一个物品. 1.传送带为空,则允许生产者放置物品,否则不许放(生产者线程wait). 2.生产者放置完物品后,通知消费者可以拿了(线程通信,notify 或者notifyAll). 2.传送带不空,则允许消费者拿物品,否则不许拿(消费者线程wait). 3.消费者拿走物品后,通知生产者可以继续生产(线程通信,notify

聊聊并发——生产者消费者模式

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式. 什么是生产者消费者模式 生产者

生产者消费者模式(1)

http://blog.csdn.net/kzq_qmi/article/details/46945753 生产者消费者问题(Producer-consumer problem)是一个多线程同步问题的经典案例.该问题描述了两个共享固定大小缓冲区的线程--即所谓的"生产者"和"消费者"--在实际运行时会发生的问题.生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程.与此同时,消费者也在缓冲区消耗这些数据.该问题的关键就是要保证生产者不会在缓冲区满时加入数据

Java并发程序设计(十一)设计模式与并发之生产者-消费者模式

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

Java线程同步与死锁、生产者消费者模式以及任务调度等

一.Thread类基本信息方法 package Threadinfo; public class MyThread implements Runnable{ private boolean flag = true; private int num = 0; @Override public void run() { while(flag) { System.out.println(Thread.currentThread().getName()+"-->"+num++); } }

java 多线程并发系列之 生产者消费者模式的两种实现

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式. 什么是生