使用BlockingQuery实现生产者者消费者:考虑并发,解耦。

生产者消费者模式是面向过程的设计模式。

生产者制造数据   ------》 生产者把数据放入缓冲区  -------》   消费者把数据取出缓冲区   --------》相当于消费者处理数据

BlockingQuery学习

支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(nullfalse,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

  抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查 element() peek() 不可用 不可用

BlockingQueue 不接受 null 元素。试图 addputoffer 一个 null 元素时,某些实现会抛出 NullPointerExceptionnull 被用作指示 poll 操作失败的警戒值。

BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个 remainingCapacity,超出此容量,便无法无阻塞地 put 附加元素。没有任何内部容量约束的 BlockingQueue 总是报告 Integer.MAX_VALUE 的剩余容量。

BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持 Collection 接口。因此,举例来说,使用 remove(x) 从队列中移除任意一个元素是有可能的。然而,这种操作通常 会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。

BlockingQueue 实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的 Collection 操作(addAllcontainsAllretainAllremoveAll没有 必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了 c 中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。

BlockingQueue 实质上 支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。这种功能的需求和使用有依赖于实现的倾向。例如,一种常用的策略是:对于生产者,插入特殊的 end-of-streampoison 对象,并根据使用者获取这些对象的时间来对它们进行解释。

生产者code

package com.liruilong.concurrent.Producer_Consuner;

import javax.swing.text.StyledEditorKit;
import java.util.concurrent.BlockingQueue; /**
* @Description : 生产者
* @Author: Liruilong
* @Date: 2019/8/22 7:24
*/
public class Producer implements Runnable{ private find BlockingQueue<String> queue; public Producer(BlockingQueue<String> queue){
this.queue = queue;
}
@Override
public void run() {
try {
String temp = "产品:"+Thread.currentThread().getName();
System.out.println("生产产品: "+Thread.currentThread().getName());
queue.put(temp); //队列已满,阻塞队列。
}catch (InterruptedException e){
e.printStackTrace();
}
}
}

消费者code

package com.liruilong.concurrent.Producer_Consuner;

import java.util.concurrent.BlockingQueue;

/**
* @Description : 消费者
* @Author: Liruilong
* @Date: 2019/8/22 7:56
*/
public class Consumer implements Runnable{
private find BlockingQueue<String> queue; public Consumer(BlockingQueue<String> queue) { this.queue = queue;
}
@Override
public void run() {
try {
// 队列为空,阻塞当前线程
String temp = queue.take();
System.out.println("消费产品:" + temp);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}

测试

package com.liruilong.concurrent.Producer_Consuner;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; /**
* @Description : 生产者消费者测试
* @Author: Liruilong
* @Date: 2019/8/22 8:01
*/
public class Test {
public static void main(String[] args) {
// 一个基于已链接节点的、任选范围的阻塞双端队列。
BlockingQueue<String> query = new LinkedBlockingQueue<>(2);
Consumer consumer = new Consumer(query);
Producer producer = new Producer(query);
for (int i = 0; i < 5; i ++){
new Thread(producer,"Producer" + (i + 1)).start(); new Thread(consumer, "Consumer" + (i + 1)).start();
}
}
}

 jdk1.6API中关于生产者消费者模式书写:

package com.liruilong.concurrent.Producer_Consuner;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque; /**
* @Description :
* @Author: Liruilong
* @Date: 2019/8/22 8:43
*/
public class Code { public static void main(String[] args) { new Code().new Setup().main();
} class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) {
queue.put(produce());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
Object produce() {
System.out.println("生产商品啦!");
return "商品";
}
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) {
consume(queue.take());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void consume(Object x) { System.out.println("商品被消费掉啦!");
}
}
class Setup {
void main() {
BlockingQueue q = new LinkedBlockingDeque(4);
// 生产者
Producer p = new Producer(q);
// 消费者
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q); Thread threadProducer = new Thread(p);
while ( !threadProducer.isInterrupted()) {
// 生产商品
threadProducer.start();
// 消费商品
new Thread(c1).start();
new Thread(c2).start();
threadProducer.interrupt();
}
}
} }

生产者消费者代码学习,Producer_Consuner的更多相关文章

  1. Linux 进程间通信(包含一个经典的生产者消费者实例代码)

    前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...

  2. 基于kafka_2.11-2.1.0实现的生产者和消费者代码样例

    1.搭建部署好zookeeper集群和kafka集群,这里省略. 启动zk: bin/zkServer.sh start conf/zoo.cfg. 验证zk是否启动成功: bin/zkServer. ...

  3. java线程之多个生产者消费者

    温故一下上一节所学习的生产者消费者代码: 两个线程时: 通过标志位flag的if判断和同步函数互斥较好解决两个线程,一个生产者.一个消费者交替执行的功能 类名:ProducterConsumerDem ...

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

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  5. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  6. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  7. 多线程-生产者消费者(synchronized同步)

    正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语 ...

  8. Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码

    说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...

  9. 生产者与消费者 代码实现 java

    首先,我利用忙测试写出了第一次版本的代码 package How; //自写代码 缺陷 无法完全实现pv操作线程处于忙测试状态 public class bin_1_1 { public static ...

随机推荐

  1. CodeForces Goodbye 2017

    传送门 A - New Year and Counting Cards •题意 有n张牌,正面有字母,反面有数字 其中元音字母$a,e,o,i,u$的另一面必须对应$0,2,4,6,8$的偶数 其他字 ...

  2. Java 高效代码50例

    导读 世界上只有两种物质:高效率和低效率:世界上只有两种人:高效率的人和低效率的人.----萧伯纳 常量&变量 直接赋值常量,禁止声明新对象 直接赋值常量值,只是创建了一个对象引用,而这个对象 ...

  3. The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力)

    The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力) 传送门:https://nanti.jisuanke.com/ ...

  4. k8s的持久化存储

    本例使用nfs 创建pv [root@k8s-master data]# vi pv.yaml apiVersion: v1kind: PersistentVolumemetadata: name: ...

  5. 利用Aspose.cells 将查询出的数据导出为excel,并在浏览器中下载。

    正题前的唠叨 本人是才出来工作不久的小白菜一颗,技术很一般,总是会有遇到一些很简单的问题却不知道怎么做,这些问题可能是之前解决过的.发现这个问题,想着提升一下自己的技术水平,将一些学的新的‘好’东西记 ...

  6. acwing 102 -利用二分枚举区间平均值

    我真的是服了,看了一晚上发现居然,,,,, 上图吧,话说有人评论没... 对于结果来说,不一定要枚举有序数列,感觉这是一种猜结果的方法,只不过特别精确,令人发指 #include<cstdio& ...

  7. HDU3886 Final Kichiku “Lanlanshu” 题解 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3886 题目大意: 给一定区间 \([A,B]\) ,一串由 /, \ , - 组成的符号串.求满足符号 ...

  8. 「BZOJ1722」「Usaco2006 Mar」Milk Team Select产奶比赛 解题报告

    Milk Team Select 产奶比赛 Description Farmer John's N (\(1 \le N \le 500\)) cows are trying to select th ...

  9. 极光推送SDK通过泰尔终端实验室检测,符合统一推送接口标准

    1月7日,中国深圳--国内领先的开发者服务提供商极光(Aurora Mobile, NASDAQ:JG)宣布其旗下产品极光推送SDK通过中国信息通信研究院泰尔终端实验室的检测,其性能和接口标准符合统一 ...

  10. 结合docker发布前端项目(基于npm包管理)的shell脚本

    结合docker发布前端项目(基于npm包管理)的shell脚本 本教程依据个人理解并经过实际验证为正确,特此记录下来,权当笔记. 注:基于linux操作系统 目前主流的前后端分离的项目中,常常在部署 ...