热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于java:Java中的设计模式二生产者消费者模式与观察者模式

在上一篇Java中的设计模式(一):观察者模式中咱们理解了观察者模式的基本原理和应用场景,在明天的这篇文章中咱们要做一点简略的延伸性学习——比照一下生产者-消费者模式和观察者模式的异同。

工具与资源核心
帮忙开发者更加高效的工作,提供围绕开发者全生命周期的工具与资源
https://developer.aliyun.com/…

一、前言

  在上一篇 Java中的设计模式(一):观察者模式 中咱们理解了 观察者模式 的基本原理和应用场景,在明天的这篇文章中咱们要做一点简略的延伸性学习——比照一下 生产者-消费者模式 和 观察者模式 的异同。

二、什么是“生产者-消费者模式”?

  和观察者模式不同,生产者-消费者模式 自身并不属于设计模式中的任何一种 。那么生产者-消费者模式到底是什么呢?上面咱们用一个例子简略阐明一下:

  如同上图中所示,生产者和消费者就如同一本杂志的投稿作者和订阅的读者,同一本杂志的投稿作者能够有多个,它的读者也能够有多个,而杂志就是连贯作者和读者的桥梁(即缓冲区)。通过杂志这个数据缓冲区,作者能够将实现的作品投递给订阅了杂志的读者,在这一过程中,作者不必关怀读者是否收到了作品或是否实现了浏览,作者和读者是两个绝对独立的对象,两者的行为互不影响。
  能够看到,在这个例子当中呈现了三个角色,别离是 生产者 、 消费者 以及 缓冲区 。生产者和消费者比拟好了解,前者是生产数据,后者则是解决前者生产进去的数据。而缓冲区在生产者-消费者模式中则起到了一个 解耦 、 反对异步 、 反对忙闲不均 的作用。

三、两者的区别

1. 编程范式不同

  生产者-消费者模式和观察者模式的第一个不同点在下面曾经说过,前者是一种 面向过程 的软件设计模式,不属于Gang of Four提出的23种设计模式中的任何一种,而后者则是23中设计模式中的一种,也即面向对象的设计模式中的一种。

2. 关联关系不同

  这一理念上的不同就带出了下一种不同点,即观察者模式中只有一对多的关系,没有多对多的关系,而在生产者-消费者模式中则是多对多的关系。
  在观察者模式中,被观察者只有一个,观察者却能够有多个。就比方十字路口的交通灯,直行的车辆只会察看管制直行的交通灯,不会去察看管制左拐或者右拐的交通灯,也就是说察看的对象是固定惟一的。
  而在生产者-消费者模式中则不同,生产者能够有多个,消费者也能够有多个。还是用下面作者和读者的例子,在这个例子当中,读者只关怀杂志的内容而不用关怀内容的创作者是谁,作者也只须要晓得创作完的作品能够公布到对应的杂志,而不用关怀会有那些读者。

3. 耦合关系不同

  从上一个不同中不难看出生产者-消费者模式和观察者模式的耦合关系也不雷同,前者为 轻耦合 ,后者为 重耦合 。

4. 利用场景不同

  观察者模式多用于 事件驱动模型 当中,生产者-消费者模式则多呈现在 过程间通信 ,用于进行解耦和并发解决,咱们罕用的音讯队列用的就是生产者-消费者模式。当然在Java中应用生产者-消费者模式还须要留神缓冲区的线程平安问题,这里就不做过多叙述。

四、一个小例子

  最初用一个简略的demo来完结本次的延长学习。

1. StoreQueue–缓冲区

public class StoreQueue {
    private final BlockingQueue queue = new LinkedBlockingQueue<>();
    /**
     * 队列中减少数据
     *
     * @param data 生产者生产的数据
     */
    public void add(T data) {
        try {
            queue.put(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 队列中获取数据
     *
     * @return 从队列中获取到的数据
     */
    public T get() {
        try {
            return queue.take();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

  在这个例子中,咱们应用了jdk本身的 阻塞队列BlockingQueue 来实现了一个缓冲区,这里只须要实现放数据和取数据的办法。如果咱们本人实现一个阻塞队列,一方面须要留神阻塞的解决,另一方面须要思考线程平安的问题,这里就不开展叙述了,有趣味的同学能够看下BlockingQueue的源码。

2. Producer&#8211;生产者

public class Producer implements Runnable{
    private StoreQueue storeQueue;
    public Producer(StoreQueue storeQueue) {
        this.storeQueue = storeQueue;
    }
    @Override
    public void run() {
        for (int i = 0; i <10; i++) {
            storeQueue.add(Thread.currentThread().getName() + ":" + i);
        }
    }
}

3. Consumer&#8211;消费者

public class Consumer implements Runnable{
    private StoreQueue storeQueue;
    public Consumer(StoreQueue storeQueue) {
        this.storeQueue = storeQueue;
    }
    @Override
    public void run() {
        try {
            while (true) {
                String data = storeQueue.get();
                System.out.println("以后生产线程 : " + Thread.currentThread().getName() + ", 接管到数据 : " + data);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
}

4. 执行逻辑和运行后果

执行逻辑

public static void main(String[] args) {
        StoreQueue storeQueue = new StoreQueue<>();
        Producer producer = new Producer(storeQueue);
        Consumer cOnsumer= new Consumer(storeQueue);
        Producer producerTwo = new Producer(storeQueue);
        Consumer cOnsumerTwo= new Consumer(storeQueue);
        new Thread(producer).start();
        new Thread(consumer).start();
        new Thread(producerTwo).start();
        new Thread(consumerTwo).start();
    }

运行后果

以后生产线程 : Thread-1, 接管到数据 : Thread-0:0
以后生产线程 : Thread-1, 接管到数据 : Thread-0:1
以后生产线程 : Thread-1, 接管到数据 : Thread-0:2
以后生产线程 : Thread-1, 接管到数据 : Thread-0:3
以后生产线程 : Thread-1, 接管到数据 : Thread-0:4
以后生产线程 : Thread-3, 接管到数据 : Thread-0:5
以后生产线程 : Thread-3, 接管到数据 : Thread-0:7
以后生产线程 : Thread-3, 接管到数据 : Thread-0:8
以后生产线程 : Thread-3, 接管到数据 : Thread-0:9
以后生产线程 : Thread-3, 接管到数据 : Thread-2:0
以后生产线程 : Thread-3, 接管到数据 : Thread-2:1
以后生产线程 : Thread-3, 接管到数据 : Thread-2:2
以后生产线程 : Thread-3, 接管到数据 : Thread-2:3
以后生产线程 : Thread-3, 接管到数据 : Thread-2:4
以后生产线程 : Thread-3, 接管到数据 : Thread-2:5
以后生产线程 : Thread-3, 接管到数据 : Thread-2:6
以后生产线程 : Thread-3, 接管到数据 : Thread-2:7
以后生产线程 : Thread-3, 接管到数据 : Thread-2:8
以后生产线程 : Thread-3, 接管到数据 : Thread-2:9
以后生产线程 : Thread-1, 接管到数据 : Thread-0:6

  能够看到在下面的数据后果中,不同生产者生产的数据只会被一个消费者生产,没有呈现线程平安问题,这要归功于实现缓冲区应用到的 BlockingQueue 。

本文转自:https://developer.aliyun.com/&#8230;


推荐阅读
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文探讨了如何通过一系列技术手段提升Spring Boot项目的并发处理能力,解决生产环境中因慢请求导致的系统性能下降问题。 ... [详细]
  • 使用WinForms 实现 RabbitMQ RPC 示例
    本文通过两个WinForms应用程序演示了如何使用RabbitMQ实现远程过程调用(RPC)。一个应用作为客户端发送请求,另一个应用作为服务端处理请求并返回响应。 ... [详细]
  • 开发笔记:9.八大排序
    开发笔记:9.八大排序 ... [详细]
  • 本文探讨了在C++中如何有效地清空输入缓冲区,确保程序只处理最近的输入并丢弃多余的输入。我们将介绍一种不阻塞的方法,并提供一个具体的实现方案。 ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • 哈密顿回路问题旨在寻找一个简单回路,该回路包含图中的每个顶点。本文将介绍如何判断给定的路径是否构成哈密顿回路。 ... [详细]
  • C语言基础入门:7个经典小程序助你快速掌握编程技巧
    本文精选了7个经典的C语言小程序,旨在帮助初学者快速掌握编程基础。通过这些程序的实践,你将更深入地理解C语言的核心概念和语法结构。 ... [详细]
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 本文探讨了使用C#在SQL Server和Access数据库中批量插入多条数据的性能差异。通过具体代码示例,详细分析了两种数据库的执行效率,并提供了优化建议。 ... [详细]
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
author-avatar
黑夜乱来
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有