使用BlockingQuery实现生产者者消费者:考虑并发,解耦。
生产者消费者模式是面向过程的设计模式。
生产者制造数据 ------》 生产者把数据放入缓冲区 -------》 消费者把数据取出缓冲区 --------》相当于消费者处理数据
BlockingQuery学习
支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。
BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:
BlockingQueue 不接受 null 元素。试图 add、put 或 offer 一个 null 元素时,某些实现会抛出 NullPointerException。null 被用作指示 poll 操作失败的警戒值。
BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个 remainingCapacity,超出此容量,便无法无阻塞地 put 附加元素。没有任何内部容量约束的 BlockingQueue 总是报告 Integer.MAX_VALUE 的剩余容量。
BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持 Collection 接口。因此,举例来说,使用 remove(x) 从队列中移除任意一个元素是有可能的。然而,这种操作通常不 会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。
BlockingQueue 实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的 Collection 操作(addAll、containsAll、retainAll 和 removeAll)没有 必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了 c 中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。
BlockingQueue 实质上不 支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。这种功能的需求和使用有依赖于实现的倾向。例如,一种常用的策略是:对于生产者,插入特殊的 end-of-stream 或 poison 对象,并根据使用者获取这些对象的时间来对它们进行解释。
生产者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 queue;
public Producer(BlockingQueue 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 queue;
public Consumer(BlockingQueue 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 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();
}
}
}
}
Linux 进程间通信(包含一个经典的生产者消费者实例代码)
前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...
基于kafka_2.11-2.1.0实现的生产者和消费者代码样例
1.搭建部署好zookeeper集群和kafka集群,这里省略. 启动zk: bin/zkServer.sh start conf/zoo.cfg. 验证zk是否启动成功: bin/zkServer. ...
java线程之多个生产者消费者
温故一下上一节所学习的生产者消费者代码: 两个线程时: 通过标志位flag的if判断和同步函数互斥较好解决两个线程,一个生产者.一个消费者交替执行的功能 类名:ProducterConsumerDem ...
java 多线程并发系列之 生产者消费者模式的两种实现
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...
Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...
多线程-生产者消费者(synchronized同步)
正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语 ...
Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码
说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...
生产者与消费者 代码实现 java
首先,我利用忙测试写出了第一次版本的代码 package How; //自写代码 缺陷 无法完全实现pv操作线程处于忙测试状态 public class bin_1_1 { public static ...
随机推荐
深度剖析Linux与Windows系统的区别
当我们每个人接触Linux之前,应该先接触的都是windows吧?但我们一般接触Linux后,习惯linux的管理和使用方法后,我们再回过头再来使用windows的时候,内心其实是拒绝的.我们会觉得图 ...
asp.net mvc4 System.Web.Optimization找不到引用
在MVC4的开发中,如果创建的项目为空MVC项目,那么在App_Start目录下没有BundleConfig.cs项的内容,在手动添加时在整个库中都找不到:System.Web.Optimizatio ...
java匿名对象_面向对象
class Student{ public void tell(){ System.out.println("Hello jikexueyuan"); } public void ...
selenium python (一) 开发环境搭建
1.工具下载: python工具共包括三个:python.setuptools.pip ² python:http://python.org/getit/ python开发环境: ² se ...
Zendframework 模块加载事件触发顺序。
模块加载时事件触发的时间顺序: 0.loadModules(ModuleEvent::EVENT_LOAD_MODULES) 1. loadModule.resolve(ModuleEvent::E ...
c#WebBrowser进阶
WebBrowser的基本功能就是访问网页,但是由于它本身就不在主线程上面,所以程序判断它什么时候加载完成了,比较麻烦.为此我集合从网上找到的内容,做了一个例子. 其中包括了给WebBrowser设置 ...
轻松学会ES6新特性之生成器
生成器虽然是ES6最具魔性的新特性,但也是最难懂得的一节,笔者写了大量的实例来具体化这种抽象的概念,能够让人一看就懂,目的是希望别人不要重复或者减少笔者学习生成器的痛苦经历. 在说具体的ES6生成器之 ...
Yii2的Gridview应用技巧补充
Yii2框架下的Gridview通常用来展示一张DB表中的数据,十分方便.这里只说一下经常要用到的一些小技巧,其实大多数官方文档都是有的,只是有可能需要在多个文档里. 自动创建的gridview示例. ...
远程访问服务器tensorboard
转自https://blog.csdn.net/Hansry/article/details/83004648 1. 在登录远程服务器的时候使用命令: : server_name@server.add ...
逻辑读为何消耗CPU?
在数据库系统中,经常会看到这个说法:“逻辑读很消耗CPU”,然后开始把这句话当作一个定理来使用.但是为什么“同样是读,为什么逻辑读会使用那么多CPU?” 查了一些资料,配合自己的理解,有下面几点体会: ...