[笔记][Java7并发编程实战手册]3.8 并发任务间的数据交换Exchanger
2015-08-23 22:15
441 查看
[笔记][Java7并发编程实战手册]系列目录
允许两个线程在某一个点进行数据交换。
exchanger.exchange(v)的时候,当前线程会被阻塞,直到另一个线程执行该方法,同时完成数据的交换
类似这种数据交换的,生产者线程一定要先生产数据,再交换数据,消费者线程一定要先交换数据,再消费数据,否则会出现少消费数据的现象
某一次运行结果:
结果说明
看上面的结果,可以发现两个线程是并行执行的,只有在交换的时候,交换数据同步点。
是不是觉得看着不明所以,这样看
————————生产者生产第 0次
生产了商品:727
第0次生产商品是 727,
[b]***********[/b]消费者消费第 0次
消费了商品:727
第0次消费的也是727, 这就说明了。两个线程之间交换数据是我们想要的结果。
假如:我们把 下面的执行顺序调换下,让consumer在前,结果你发现还是先生产后消费。这个是为什么呢?
是因为:
1. 从java内存模型角度来说,上面两行代码没有数据依赖性(在实际执行的时候他们的顺序不一定是谁先谁后)
2. 原因就出现在exchanger.exchange(v)方法,就算是消费者先执行,仔细看代码,消费者会先执行exchanger.exchange(v)方法,如果之前没有线程执行该方法,那么消费者则会休眠等待生产者执行该方法。
简介
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,
[b]***********[/b]消费者消费第 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)方法,如果之前没有线程执行该方法,那么消费者则会休眠等待生产者执行该方法。
相关文章推荐
- java多线程详解(1)-多线程入门
- java EE 5,JSP中核心标签库的无法使用
- Spring JdbcTemplate batchUpdate() example
- Java多线程编程-同步代码块
- JavaSE复习日记 : 实例化对象/构造方法和this关键字
- mvn学习
- 用 ObjectMapper将JSON字符串转换为java对象时,java对象一定要有无参构造函数
- cglib动态代理和jdk的动态代理
- Spring JdbcTemplate Querying examples
- synchronized 和java.util.concurrent.locks.Lock 的异同
- Spring的简介
- Java技术资料
- java基础和面向对象
- 文章标题
- 正则表达式笔记(第二弹:JAVA中正则表达式的应用)
- Java编程语言概述
- java多线程同步及最大线程数目
- Java Collection详解,Java中的集合框架Collection上
- eclipse的包的加减号展开方式
- java-查找字符串