[笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger
简单介绍
Exchanger 是一个同步辅助类。用于两个并发线程之间在一个同步点进行数据交换。
同意两个线程在某一个点进行数据交换。
本章exchanger 使用心得总结
- 两个线程必须使用同一个Exchanger对象,且仅仅能是两个线程间的数据交换
- exchanger.exchange(v)的时候,当前线程会被堵塞,直到还有一个线程运行该方法,同一时候完成数据的交换
- 相似这样的数据交换的,生产者线程一定要先生产数据。再交换数据,消费者线程一定要先交换数据,再消费数据,否则会出现少消费数据的现象
演示样例
场景描写叙述:一对一的 生产者和消费者。生产者每次生产5个商品,然后消费者把空的商品容器和生产者交换。
/**
* Created by zhuqiang on 2015/8/23 0023.
*/
public class Client {
public static void main(String[] args) {
Exchanger<ArrayList<String>> exchanger = new Exchanger<ArrayList<String>>();
new Thread(new Producer(exchanger)).start();
new Thread(new Consumer(exchanger)).start();
}
}
// 生产者
class Producer implements Runnable {
private ArrayList<String> goods = new ArrayList<String>(); //商品容器
private Exchanger<ArrayList<String>> exchanger = new Exchanger<ArrayList<String>>();
public Producer(Exchanger<ArrayList<String>> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) { //生产3次
System.out.println("------------------------生产者生产第 " + i + "次");
for (int j = 0; j < 3; j++) { //每次生产3个商品
String e = (long) (Math.random() * 1000) + "";
goods.add(e);
System.out.println("生产了商品:" + e);
}
try {
goods = exchanger.exchange(goods); //交换数据
System.out.println("生产者:数据交换完成:获得交换的商品容器大小:" + goods.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class Consumer implements Runnable {
private ArrayList<String> goods = new ArrayList<String>(); //商品容器
private Exchanger<ArrayList<String>> exchanger = new Exchanger<ArrayList<String>>();
public Consumer(Exchanger<ArrayList<String>> exchanger) {
this.exchanger = exchanger;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) { //消费3次
try {
goods = exchanger.exchange(goods); //交换数据
System.out.println("消费者:数据交换完成:获得交换的商品容器大小:" + goods.size());
// 消费商品
Iterator<String> it = goods.iterator();
if (goods.size() > 0) {
System.out.println("*********************消费者消费第 " + i + "次");
while (it.hasNext()) {
String next = it.next();
System.out.println("消费了商品:" + next);
it.remove(); //移除消费了的商品
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
某一次运行结果:
------------------------生产者生产第 0次
生产了商品:727
生产了商品:671
生产了商品:345
生产者:数据交换完成:获得交换的商品容器大小:0
------------------------生产者生产第 1次
生产了商品:67
生产了商品:466
生产了商品:207
消费者:数据交换完成:获得交换的商品容器大小:3
*********************消费者消费第 0次
消费了商品:727
消费了商品:671
消费了商品:345
消费者:数据交换完成:获得交换的商品容器大小:3
生产者:数据交换完成:获得交换的商品容器大小:0
------------------------生产者生产第 2次
*********************消费者消费第 1次
消费了商品:67
消费了商品:466
消费了商品:207
生产了商品:38
生产了商品:355
生产了商品:24
生产者:数据交换完成:获得交换的商品容器大小:0
消费者:数据交换完成:获得交换的商品容器大小:3
*********************消费者消费第 2次
消费了商品:38
消费了商品:355
消费了商品:24
结果说明
看上面的结果,能够发现两个线程是并行运行的,仅仅有在交换的时候,交换数据同步点。
是不是认为看着不明所以。这样看
————————生产者生产第 0次
生产了商品:727
第0次生产商品是 727。
***********消费者消费第 0次
消费了商品:727
第0次消费的也是727, 这就说明了。两个线程之间交换数据是我们想要的结果。
假如:我们把 以下的运行顺序调换下,让consumer在前。结果你发现还是先生产后消费。
这个是为什么呢?
new Thread(new Producer(exchanger)).start();
new Thread(new Consumer(exchanger)).start();
是由于:
1. 从java内存模型角度来说。上面两行代码没有数据依赖性(在实际运行的时候他们的顺序不一定是谁先谁后)
2. 原因就出如今exchanger.exchange(v)方法。就算是消费者先运行,细致看代码。消费者会先运行exchanger.exchange(v)方法。假设之前没有线程运行该方法,那么消费者则会休眠等待生产者运行该方法。
[笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger的更多相关文章
- [笔记][Java7并发编程实战手冊]系列文件夹
推荐学习多线程之前要看的书. [笔记][思维导图]读深入理解JAVA内存模型整理的思维导图文章里面的思维导图或则相应的书籍.去看一遍. 能理解为什么并发编程就会出现故障. Java7并发编程实战手冊 ...
- [笔记][Java7并发编程实战手冊]3.4 等待多个并发事件的完毕CountDownLatch倒计数闭锁
[笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 本文学习CountDownLatch 倒计数闭锁. 本人英文不好.靠机器翻译,然后有一段非常形象的描写叙述,让我把它叫为倒计数 用给定的计数 ...
- 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
<Java并发编程实战>和<Java并发编程的艺术> Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...
- 【Java并发编程实战】—–synchronized
在我们的实际应用其中可能常常会遇到这样一个场景:多个线程读或者.写相同的数据,訪问相同的文件等等.对于这样的情况假设我们不加以控制,是非常easy导致错误的. 在java中,为了解决问题,引入临界区概 ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- 《 .NET并发编程实战》一书中的节流为什么不翻译成限流
有读者问,为什么< .NET并发编程实战>一书中的节流为什么不翻译成限流? 这个问题问得十分好!毕竟“限流”这个词名气很大,耳熟能详,知名度比“节流”大多了. 首先,节流的原词Thrott ...
- 《Java7并发编程实战手册》读书笔记
一.线程管理 1.线程的创建和运行 创建线程的2种方式: 继承Thread类,并覆盖run()方法 创建一个实现Runnable接口的类.使用带参数的Thread构造器来创建Thread对象 每个Ja ...
- 《Go并发编程实战》读书笔记-语法概览
<Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...
- 《Go并发编程实战》读书笔记-初识Go语言
<Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...
随机推荐
- RxSwift 系列(八)
前言 本篇文章我们将学习RxSwift中的错误处理,包括: catchErrorJustReturn catchError retry retry(_:) catchErrorJustReturn 遇 ...
- 执行Shell脚本的4种方法及区别介绍(转)
原文地址: http://www.jb51.net/article/66824.htm 执行shell脚本有以下几种方式 ###1.相对路径方式,需先cd到脚本路径下 [root@banking tm ...
- java中的多线程 // 基础
java 中的多线程 简介 进程 : 指正在运行的程序,并具有一定的独立能力,即 当硬盘中的程序进入到内存中运行时,就变成了一个进程 线程 : 是进程中的一个执行单元,负责当前程序的执行.线程就是CP ...
- 配置Maven环境变量与Intelij IDE配置Maven
Maven有什么用? 以前我们导入第三方jar包的流程是什么?一般是download,然后copy到项目中,然后依赖(library)项目,最后被我们使用. 通俗的说,就是不用我们自己去downloa ...
- js判断移动设备
在开发中可能需要去判断用户的设备重定向到相应的网址: 1. 判断 iPhone Android iPod if((navigator.userAgent.match(/iPhone/i))||(n ...
- Object-C—集合
Obejct-C中包含了三种集合,分别是:数组.字典和集(set). 数组和C语言中的数组相似,但是OC中的数组只能存储对象,不能存储基本数据类型,如int.float.enum.stru ...
- Time Step Too Small in Multisim
http://digital.ni.com/public.nsf/allkb/4B99B2CD6C0C3B6A86257205005D58E0 Error: Time Step Too Small i ...
- android——根据MVC框架设计的结构
- 关于如何在你的Web项目中实现对空间数据访问权限的控制(一)
Wednesday, 23 JUNE 近来一直在研究关于如何在我的WebGIS项目中实现对空间数据(已发布在GeoServer上)进行权限管理的问题.虽然到目前为止没能找到一个完美的解决方案,但通过这 ...
- linux如何后台运行进程,而且不随终端关闭而关闭
参考:http://www.cnblogs.com/kaituorensheng/p/3980334.html 使用命令nohup:no hang up,表示关闭终端后,进程并不随着终端关闭而关闭 f ...