Java生产者消费者模式
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦,如工厂模式的第三者是工厂类,模板模式的第三者是模板类。
生产者消费者模式实战
利用BlockingQueue
package com; import java.util.Random;
import java.util.concurrent.BlockingQueue; public class Comsumer implements Runnable {
private BlockingQueue<PCData> queue;
private static final int SLEEPTIME = 1000;
public Comsumer(BlockingQueue<PCData> queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("start Consumer Id:"+Thread.currentThread().getId());
Random r = new Random();
Boolean isrunning = true;
try {
while(isrunning){
PCData data = queue.take();
if(data != null){
System.out.println("Comsumer data:"+data);
Thread.sleep(r.nextInt(SLEEPTIME));
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
package com; import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class Producer implements Runnable{
private volatile boolean isRunning = true;
//内存缓冲区
private BlockingQueue<PCData> queue;
//总数 AtomicInteger
private static AtomicInteger count = new AtomicInteger();
private static final int SLEEPTIME = 1000; public Producer(BlockingQueue<PCData> queue){
this.queue = queue;
} public void run(){
PCData data = null;
Random r = new Random();
System.out.println("start producting id:"+ Thread.currentThread().getId());
while(isRunning){
try {
while(isRunning){
Thread.sleep(r.nextInt(SLEEPTIME));
data = new PCData(count.incrementAndGet());
if(!queue.offer(data,2,TimeUnit.SECONDS)){
System.out.println("加入队列失败");
}else{
System.out.println("Producer data:"+data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
} public void stop(){
isRunning = false;
}
}
package com; 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;
}
}
package com; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; public class Main {
public static void main(String[] args) throws InterruptedException{
BlockingQueue<PCData> queue = new LinkedBlockingQueue<>(10);
Producer p1 = new Producer(queue);
Producer p2 = new Producer(queue);
Producer p3 = new Producer(queue);
Comsumer c1 = new Comsumer(queue);
Comsumer c2 = new Comsumer(queue);
Comsumer c3 = new Comsumer(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(10*1000);
p1.stop();
p2.stop();
p3.stop();
Thread.sleep(3000);
service.shutdown();
}
}
利用notifyAll和wait
package com; import java.util.List; public class Consumer implements Runnable{
private List<PCData> queue;
public Consumer(List<PCData> queue){
this.queue = queue;
} @Override
public void run() {
while(true){
PCData data = null;
try {
synchronized (queue) {
if(queue.size() == 0){
System.out.println(Thread.currentThread().getId()+"队列为空,无法消费");
queue.notifyAll();
queue.wait();
}else{
data = queue.remove(0);
System.out.println(Thread.currentThread().getId()+"消费:"+data);
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com; import java.util.List;
import java.util.Random; public class Producer implements Runnable {
private List<PCData> queue;
private int length; public Producer(List<PCData> queue,int length){
this.queue = queue;
this.length = length;
} @Override
public void run() {
while(true){
Random r = new Random();
PCData data = new PCData(r.nextInt(100));
try {
synchronized (queue) {
if(queue.size() >= length){
System.out.println(Thread.currentThread().getId()+"队列满了,无法加入 ");
queue.notifyAll();
queue.wait();
}else{
queue.add(data);
System.out.println(Thread.currentThread().getId()+"生产了:"+data);
}
}
Thread.sleep(1000);
} catch (InterruptedException e){
e.printStackTrace();
}
} } }
package com; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Main {
public static void main(String[] args){
List<PCData> queue = new ArrayList<>();
int length =10;
Producer p1 = new Producer(queue, length);
Producer p2 = new Producer(queue, length);
Producer p3 = new Producer(queue, length);
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);
}
}
Java生产者消费者模式的更多相关文章
- 基于Java 生产者消费者模式(详细分析)
Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...
- Java 生产者消费者模式详细分析
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- java生产者/消费者模式实现——一生产者一消费者(操作值)
胶多不粘话多不甜,直接上代码: 生产者类: /** * Created by 51304 on 2016/2/28. */ public class P { private String lock; ...
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比
package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...
- Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码
说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...
- Java多线程-----实现生产者消费者模式的几种方式
1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...
- java设计模式之生产者/消费者模式
什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者 ...
随机推荐
- BZOJ 1137: [POI2009]Wsp 岛屿 半平面交
1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 165 Solved: ...
- 关于vcpkg的一些技术细节
1.如果你启用了vcpkg integrate install,将默认采用vcpkg里安装的源而不是nuget中的 2.一般而言xxx-uwp不能用xxx-windows代替,否则回捣乱其它包 3.卸 ...
- UVA 211 The Domino Effect 多米诺效应 (回溯)
骨牌无非两种放法,横着或竖着放,每次检查最r,c最小的没访问过的点即可.如果不能放就回溯. 最外面加一层认为已经访问过的位置,方便判断. #include<bits/stdc++.h> ; ...
- 如何从Ubuntu 16.04 LTS升级到Ubuntu 18.04 LTS
可以说非常简单(假设过程顺利!!) 您只需打开Software&Update,进入"Updates"选项卡,然后从“有新版本时通知我”下拉菜单中选择“适用长期支持版”选项. ...
- (2) html 语义化
HTML语义化标签 1 什么是语义化标签? 通过标签判断内容语义,例如根据h1标签判断出内容是标题,根据 p 判断内容是段落.input 标签是输入框等. 2 为什么要标签语义化? 1.搜素引擎友好 ...
- NOIP模拟赛 czy的后宫3
[题目描述] 上次czy在机房妥善安排了他的后宫之后,他发现可以将他的妹子分为c种,他经常会考虑这样一个问题:在[l,r]的妹子中间,能挑选出多少不同类型的妹子呢? 注意:由于czy非常丧尸,所以他要 ...
- k8s的高级调度方式
默认的scheduler的调度过程:1.预选策略:从所有节点当中选择基本符合选择条件的节点.2.优选函数:在众多符合基本条件的节点中使用优选函数,计算节点各自的得分,通过比较进行排序.3.从最高得分的 ...
- 安装ElasticSearch 6.1.1 head插件
https://blog.csdn.net/zoubf/article/details/79007908 主要参考了这个blog 才完成所有的配置,很好的参考资料
- laravel5 使用try catch
在laravel5中使用以下代码并没有捕获异常 try{ var_dump($val); }catch (Exception $e){ var_dump($e); } Laravel 5 时代控制器 ...
- virtualbox安装win7系统报错(“FATAL:No bootable medium found!”)
virtualbox属于傻瓜式安装虚拟系统,但博主安装win7系统时,无论怎么调试都还是出现截图所述样式,网上教程很多,但是都不行,其实只有一个根本原因安装的iso镜像不是原生镜像,下载的镜像已经是被 ...