[笔记][Java7并发编程实战手冊]系列文件夹


简单介绍

  Exchanger 是一个同步辅助类。用于两个并发线程之间在一个同步点进行数据交换。

  同意两个线程在某一个点进行数据交换。


本章exchanger 使用心得总结

  1. 两个线程必须使用同一个Exchanger对象,且仅仅能是两个线程间的数据交换
  2. exchanger.exchange(v)的时候,当前线程会被堵塞,直到还有一个线程运行该方法,同一时候完成数据的交换
  3. 相似这样的数据交换的,生产者线程一定要先生产数据。再交换数据,消费者线程一定要先交换数据,再消费数据,否则会出现少消费数据的现象

演示样例

场景描写叙述:一对一的 生产者和消费者。生产者每次生产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的更多相关文章

  1. [笔记][Java7并发编程实战手冊]系列文件夹

    推荐学习多线程之前要看的书. [笔记][思维导图]读深入理解JAVA内存模型整理的思维导图文章里面的思维导图或则相应的书籍.去看一遍. 能理解为什么并发编程就会出现故障. Java7并发编程实战手冊 ...

  2. [笔记][Java7并发编程实战手冊]3.4 等待多个并发事件的完毕CountDownLatch倒计数闭锁

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 本文学习CountDownLatch 倒计数闭锁. 本人英文不好.靠机器翻译,然后有一段非常形象的描写叙述,让我把它叫为倒计数 用给定的计数 ...

  3. 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结

    <Java并发编程实战>和<Java并发编程的艺术>           Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...

  4. 【Java并发编程实战】—–synchronized

    在我们的实际应用其中可能常常会遇到这样一个场景:多个线程读或者.写相同的数据,訪问相同的文件等等.对于这样的情况假设我们不加以控制,是非常easy导致错误的. 在java中,为了解决问题,引入临界区概 ...

  5. 《java并发编程实战》笔记

    <java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为:  Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...

  6. 《 .NET并发编程实战》一书中的节流为什么不翻译成限流

    有读者问,为什么< .NET并发编程实战>一书中的节流为什么不翻译成限流? 这个问题问得十分好!毕竟“限流”这个词名气很大,耳熟能详,知名度比“节流”大多了. 首先,节流的原词Thrott ...

  7. 《Java7并发编程实战手册》读书笔记

    一.线程管理 1.线程的创建和运行 创建线程的2种方式: 继承Thread类,并覆盖run()方法 创建一个实现Runnable接口的类.使用带参数的Thread构造器来创建Thread对象 每个Ja ...

  8. 《Go并发编程实战》读书笔记-语法概览

    <Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...

  9. 《Go并发编程实战》读书笔记-初识Go语言

    <Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...

随机推荐

  1. ubuntu16.04系统上安装CAJViewer方法步骤教程详解

    下载链接: http://pan.baidu.com/s/1jIqHxLs 或: http://download.csdn.net/detail/arhaiyun/5457947 安装wine1.6: ...

  2. 【BZOJ 2728】 2728: [HNOI2012]与非 (线性基?)

    2728: [HNOI2012]与非 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 813  Solved: 389 Description Inpu ...

  3. BZOJ1226 SDOI2009学校食堂

    这题状压DP太神了. g[i][j][k]表示前i-1个人都已打到饭,自己和后七个人打饭的情况是j,当前最后一个打饭的与i的关系是k 如果j&1==1说明当前这个人也打了饭,那么可以转移到g[ ...

  4. luoguP3255 [JLOI2013]地形生成 动态规划

    出题人语文真好... 各不相同的标号和高度 = 各不相同的标号 + 单独的高度... 第一问比较简单,考虑从大到小插入,在相同情况下,按关键值从小到大插入 这样子,关键大的元素一定会影响到关键小的元素 ...

  5. finish/onDestroy/System.exit()的区别

    Activity.finish():Call this when your activity is done and should be closed. 在你的activity动作完成的时候,或者Ac ...

  6. bzoj 2342: [Shoi2011]双倍回文 -- manacher

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符 ...

  7. Scrapy入门教程(转)

    关键字:scrapy 入门教程 爬虫 Spider作者:http://www.cnblogs.com/txw1958/出处:http://www.cnblogs.com/txw1958/archive ...

  8. 给WebAPI的REST接口服务添加测试页面(一)

    当使用WebAPI提供REST服务的时候,一个经常进行的操作是对接口进行测试.Asp.net WebAPI框架本身并没有提供这一接口,不过由于提供的是标准的REST服务,是可以非常方便的使用一些第三方 ...

  9. ELM327 蓝牙/WIFI/USB diagnostic interface

  10. CMSIS-SVD Reference

    http://www.keil.com/pack/doc/cmsis/svd/html/modules.html SVD File Schema Levels Device Level Periphe ...