生产者消费者代码学习,Producer_Consuner
使用BlockingQuery实现生产者者消费者:考虑并发,解耦。
生产者消费者模式是面向过程的设计模式。
生产者制造数据 ------》 生产者把数据放入缓冲区 -------》 消费者把数据取出缓冲区 --------》相当于消费者处理数据
BlockingQuery学习
支持两个附加操作的 Queue
,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。
BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:
抛出异常 | 特殊值 | 阻塞 | 超时 | |
插入 | add(e) |
offer(e) |
put(e) |
offer(e, time, unit) |
移除 | remove() |
poll() |
take() |
poll(time, unit) |
检查 | element() |
peek() |
不可用 | 不可用 |
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<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的更多相关文章
- 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 一个写缓存例子
我们已经几次提及 shortprint 驱动; 现在是时候真正看看. 这个模块为并口实现一个非 常简单, 面向输出的驱动; 它是足够的, 但是, 来使能文件打印. 如果你选择来测试这个 驱动, 但是, ...
- H3C网络监测工具命令
1.Debugging 2.Display debugging 3.Display diagnostic-information display diagnostic-information 命令用来 ...
- Canvas学习实践:一款简单的动画游戏
最近学习了下Canvas绘图...突发奇想就有了下面这款简单的小游戏,纯属娱乐~ 废话不多说,直接上代码: <!DOCTYPE html> <html lang="zh&q ...
- 布尔&list与条件循环语句与trutle
布尔值与空值 布尔值: 一个布尔值只有True.False两种值 空值: 是python里一个特殊的值,用None表示.None不能理解为0.因为0是有意义的,而None是一个特殊值. list(列表 ...
- centos6.5单用户模式拯救系统
系统出现启动异常,某个软件卡住了不能启动(按Fx键可以查看是哪个软件卡住了),需要进入单用户模式或修复模式对系统进行管理. 使用单用户模式有一个前提,只要系统引导器(grub)能正常工作,否则要进行系 ...
- python 练习题3
# 计算阶乘def factorial(n): if n>2: return n*factorial(n-1) else: return nprint(factorial(2))print(fa ...
- 图解Go里面的sync.Map了解编程语言核心实现源码
基础筑基 在大多数语言中原始map都不是一个线程安全的数据结构,那如果要在多个线程或者goroutine中对线程进行更改就需要加锁,除了加1个大锁,不同的语言还有不同的优化方式, 像在java和go这 ...
- 使用element的upload组件实现一个完整的文件上传功能(下)
本篇文章是<使用element的upload组件实现一个完整的文件上传功能(上)>的续篇. 话不多说,接着上一篇直接开始 一.功能完善—保存表格中每一列的文件列表状态 1.思路 保存表格中 ...
- 002 ceph的deploy部署
介绍:前期对ceph有一个简单的介绍,但是内容太大,并不具体,接下来使用ceph-deploy部署一个Ceph集群,并做一些运维管理工作,深入的理解Ceph原理及工作工程! 一.环境准备 本次使用的虚 ...
- windows10 powershell上切换至cmd
前言 在windows10 上是遇到了坑,因为出现了这样的情况!不要说什么盗版,公司买的正版呢. 上图是powershell,下图是 cmd,然后我同样使用powershell 与 cmd,查询nod ...