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();
}
}
生产者-消费者模式很好地对生产者线程和消费者线程进行解耦,优化了系统整体结构。同时,由于缓冲作用,允许生产者和消费者线程存在执行上的性能差异,从一定程度上解决了性能瓶颈对系统性能的影响。
Java的设计模式(7)— 生产者-消费者模式的更多相关文章
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- java设计模式之生产者/消费者模式
什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者 ...
- java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现
java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了 wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...
- 2.5多线程(Java学习笔记)生产者消费者模式
一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...
- JAVA多线程编程之生产者消费者模式
Java中有一个BlockingQueue可以用来充当堵塞队列,下面是一个桌面搜索的设计 package net.jcip.examples; import java.io.File; import ...
- Java中设计模式之生产者消费者模式-4
引言 生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区.其中一个是生产者,用于将消息放入缓冲区:另 ...
- Java并发编程()阻塞队列和生产者-消费者模式
阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到有空间可用:如果队列为空,那么take方法将会阻塞直到有元素可用.队列可以 ...
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- Java并发程序设计(十一)设计模式与并发之生产者-消费者模式
设计模式与并发之生产者-消费者模式 生产者-消费者模式是一个经典的多线程设计模式.它为多线程间的协作提供了良好的解决方案.在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程. ...
随机推荐
- Codeforces 1264C/1265E Beautiful Mirrors with queries (概率期望、DP)
题目链接 http://codeforces.com/contest/1264/problem/C 题解 吐槽:为什么我赛后看cf的题就经常1h内做出Div.1 C, 一打cf就动不动AB题不会啊-- ...
- 2、vueJs基础知识02
vue生命周期: 钩子函数: created -> 实例已经创建 √ beforeCompile -> 编译之前 compiled -> 编译之后 ready -> 插入到文档 ...
- T-MAX组--项目冲刺(第七天)
THE SEVENTH DAY 项目相关 作业相关 具体描述 所属班级 2019秋福大软件工程实践Z班 作业要求 团队作业第五次-项目冲刺 作业正文 T-MAX组--项目冲刺(第七天) 团队名称 T- ...
- AXURE RP8 - 实战手册 网站和APP原型制作案例精粹
扫码时备注或说明中留下邮箱 付款后如未回复请至https://shop135452397.taobao.com/ 联系店主
- Java ArrayList,LinkedList使用
1.ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上回在底层生成一个长度为10的Object类型数组. 2.如果增加的元素个数超过10个,那么Array ...
- Java_jdbc 基础笔记之四 数据库连接 (通用更新方法)
/** * 写一个通用的更新方法 包括 INSERT. DELETE.UPDATE * 使用工具类 * @param sql */ public void update(String sql){ Co ...
- linux cat 文件编码
test.log是utf-16的编码 cat test.log会报错 但是我们可以cat的时候指定编码格式 iconv -f 文件编码 -t 终端编码 input.log iconv -f utf-1 ...
- idea 启动web项目
1>Run>Edit Configurations... 2>Server>Open browser>URL>http://localhost:8888/demo2 ...
- 在dubbo工程中,使用druid监控
介绍:在dubbo项目中,使用druid的监控功能 问题:因为,在网上找勒,很多的资料,显示的都是需要在web.xml中配置 <servlet> <servlet-name>D ...
- snmpwalk 安装与使用详解-windows下
snmpwalk是SNMP的一个工具,它使用SNMP的GETNEXT请求查询指定OID(SNMP协议中的对象标识)入口的所有OID树信息,并显示给用户.通过snmpwalk也可以查看支持SNMP协议( ...