[Java Concurrent] 多线程合作 producer-consumers / queue 的简单案例
在多线程环境下,通过 BlockingQueue,实现生产者-消费者场景。
Toast 被生产和消费的对象。
ToastQueue 继承了 LinkedblockingQueue ,用于中间存储 Toast 。
Producer 生产 Toast ,并将生产出来的 Toast 放进队列 initialToastQ 中。
Processor 加工 Toast,从 initialToastQ 中获得生产出来的 Toast,将其加工并放进队列 finishedToast 中。
Consumer 消费 Toast,从 finishedToastQ 中获得加工完成的 Toast。
ThreadHelper 工具类,用于输出线程相关信息。
ProducerConsumerDemo 演示这个场景

代码实现:
Toast 实现
public class Toast {
private int id;
public Toast(int id){
this.id = id;
}
public String toString(){
return " toast#" + id;
}
}
ToastQueue 实现
import java.util.concurrent.LinkedBlockingQueue;
public class ToastQueue extends LinkedBlockingQueue<Toast> {
private static final long serialVersionUID = 1L;
}
Producer 循环生产 Toast
import java.util.concurrent.TimeUnit;
public class Producer implements Runnable {
private ToastQueue toastQueue;
private int count;
public Producer(ToastQueue toastQueue){
this.toastQueue = toastQueue;
this.count = 0;
}
@Override
public void run() {
try {
while (true){
TimeUnit.MILLISECONDS.sleep(100);
Toast toast = new Toast(count);
count++;
toastQueue.put(toast);
ThreadHelper.print(" produced " + toast);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Processor 从 intialToastQ 获得 Toast ,对其加工,并放进 finishedToastQ 中。
import java.util.concurrent.TimeUnit;
public class Processor implements Runnable {
private ToastQueue initialToastQ;
private ToastQueue finishedToastQ;
public Processor(ToastQueue initialToastQ, ToastQueue finishedToastQ){
this.initialToastQ = initialToastQ;
this.finishedToastQ = finishedToastQ;
}
@Override
public void run() {
try {
while (true){
Toast toast = initialToastQ.take();
ThreadHelper.print(" processing " + toast);
TimeUnit.MILLISECONDS.sleep(180);
finishedToastQ.put(toast);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Consumer 消耗 Toast
public class Consumer implements Runnable {
private ToastQueue finishedToastQ;
public Consumer(ToastQueue finishedToastQ){
this.finishedToastQ = finishedToastQ;
}
@Override
public void run() {
try {
while (true){
Toast toast = finishedToastQ.take();
ThreadHelper.print(" consumed " + toast);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ThreadHelper 线程帮助类
public class ThreadHelper {
public static void print(String msg){
System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
}
}
演示烤面包的生产、加工、消费的场景
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; public class ProducerConsumerDemo { public static void main() throws InterruptedException{ ToastQueue initialToastQ = new ToastQueue();
ToastQueue finishedToastQ = new ToastQueue(); ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Producer(initialToastQ));
exec.execute(new Processor(initialToastQ, finishedToastQ));
exec.execute(new Consumer(finishedToastQ)); TimeUnit.SECONDS.sleep(2);
exec.shutdownNow();
}
}
输出结果:
[pool--thread- ] processing toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
[pool--thread- ] processing toast#
[pool--thread- ] consumed toast#
[pool--thread- ] produced toast#
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:)
at concurrencyProducerConsumer.Consumer.run(Consumer.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:)
at concurrencyProducerConsumer.Producer.run(Producer.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:)
at concurrencyProducerConsumer.Processor.run(Processor.java:)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
at java.lang.Thread.run(Thread.java:)
参考资料
Page 868, Produer-consumers and queue, Thinking in Java
[Java Concurrent] 多线程合作 producer-consumers / queue 的简单案例的更多相关文章
- [Java Concurrent] 多线程合作 wait / notifyAll 的简单案例
本案例描述的是,给一辆汽车打蜡.抛光的场景. Car 是一辆被打蜡抛光的汽车,扮演共享资源的角色. WaxOnCommand 负责给汽车打蜡,打蜡时需要独占整部车,一次打一部分蜡,等待抛光,然后再打一 ...
- Java:多线程,java.util.concurrent.atomic包之AtomicInteger/AtomicLong用法
1. 背景 java.util.concurrent.atomic这个包是非常实用,解决了我们以前自己写一个同步方法来实现类似于自增长字段的问题. 在Java语言中,增量操作符(++)不是原子的,也就 ...
- java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...
- JAVA之多线程的创建
转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...
- Java作业-多线程
未完成,占位以后补 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 书面作业 本次PTA作业题集多线程 源代码阅读:多线程程序BounceThread 1.1 Ball ...
- 8.并发编程--多线程通信-wait-notify-模拟Queue
并发编程--多线程通信-wait-notify-模拟Queue 1. BlockingQueue 顾名思义,首先是一个队列,其次支持阻塞的机制:阻塞放入和获取队列中的数据. 如何实现这样一个队列: 要 ...
- 【Java】多线程入门
Java多线程学习(入门) 前言 目前对于线程的了解仅仅停留在学习python的threading库,很多线程的概念没有真正弄清楚,所以选择来系统性的学习多线程.那么这次选择的是Java的多线程学习, ...
- Java的多线程机制系列:(一)总述及基础概念
前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...
- Java的多线程机制系列:(三)synchronized的同步原理
synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...
随机推荐
- PHP: 深入pack/unpack <转> [链接]
PHP: 深入pack/unpack PHP: chr和pack.unpack那些 PHP: pack/unpack补遗
- HTML5之选择上传图片文件
- 7-ajax的同步和异步?
同步和异步统一根据send()执行的位置来实现分割逻辑同步:1.send()后统一不会被执行,直到http事务完成之后才会之后后续逻辑.2.堵塞send()方法的逻辑.异步:1.send()后面照样执 ...
- 使用EditText搜索listview里面的内容,实现Listview跟随变动的情况
1.布局的XML文件里面添加EditText控件(省略)控件id=mSearch ListView的id=admin_lv; 2.一.获取ListView展示的数据(通过适配器获取) 二.这个是我要说 ...
- socket.io实现
后台代码 index_server.js var app = require('http').createServer(handler)//创建服务器app , io = require('socke ...
- cxf客户端代码设置设置访问用户名、密码、证书域名不匹配认证通过
最近和第三方联调,需要调用对方的wsdl,但是调用必须的设置用户名.密码验证.在soapUI里面设置用户名.密码调用通过.但是怎么转换成JAVA代码呢,搜索了好多解决方案,现将代码截图如下: 1.SO ...
- 如何让Hadoop运行得更快一些
在数据处理方面,我们发现数据输入速度一般要比的数据处理速度快很多,这种现象在大多数据领域尤为明显.随着数据不断膨胀,相应的响应时间自然要有所增加,数据处理的复杂度也在不断提高.作为一个开发者,我们自然 ...
- jQuery中的综合动画
所谓综合动画,就是在链式表达式依次执行相关animate函数,其中的参数是以键值对的方式存在的. 如下示例,就展示了一个基本的综合动画. <!DOCTYPE html PUBLIC " ...
- Hibernate的CRUD
1.CRUD: C:sesion.save() R:session.get()? session.load() D:session.delete() U:session.update() 2.读取数据 ...
- 利用路由修改thinkphp框架开发的后台地址
一般我们写前台是home 后台是 admin那么我们的后台是 域名/admin 那我们要随时修改这个地址是非常麻烦的事情开始可能会想到,就是把模块名称改掉,或者分组(3.1版)这样的话不但要改配置,连 ...