前言

  JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch、CyclicBarrier、Semphore、Exchanger、Phaser;

  CountDownLatch、CyclicBarrier、Semphore、Phaser 这四个工具类提供一种并发流程的控制手段;而Exchanger工具类则提供了在线程之间交换数据的一种手段。

简介

   Exchanger的功能是使2个线程之间交换数据(有不少文章的说法是“传输数据”,应该叫“交换数据”更合适,因为这是两个线程都要向对方传送数据,同时也获取对方的传送过来的数据,是双向模式,并不是一个线程向另一个线程传输数据)。它比生产者/消费者模式使用的wait/notify要更加方便。

  Exchanger 提供一个同步点,在这个同步点处,两个线程可以交换彼此数据。即一个线程调用了exchange( )方法交换数据,到达了同步点,然后就会一直阻塞等待另一个线程调用exchange( )方法来交换数据。所以,要注意exchange( )方法是有阻塞的特性。

Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。

方法摘要

public V exchange(V x) throws InterruptedException

等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。

public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException

等待另一个线程到达此交换点(除非当前线程被中断,或者超出了指定的等待时间),然后将给定的对象传送给该线程,同时接收该线程的对


@ Example1 用法示例

以下是重点介绍的一个类,该类使用 Exchanger 在线程间交换缓冲区,因此,在需要时,填充缓冲区的线程获取一个新腾空的缓冲区,并将填满的缓冲区传递给腾空缓冲区的线程

class FillAndEmpty {
Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
DataBuffer initialEmptyBuffer = ... a made-up type
DataBuffer initialFullBuffer = ... class FillingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ... }
}
} class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
} void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}

@ Example2 应用场景示例

Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果。

Exchanger也可以用于校对工作。比如我们需要将纸制银流通过人工的方式录入成电子银行流水,为了避免错误,采用AB岗两人进行录入,录入到Excel之后,系统需要加载这两个Excel,并对这两个Excel数据进行校对,看看是否录入的一致。代码如下:

private static final Exchanger<String> exgr = new Exchanger<String>();
private static ExecutorService threadPool = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
String A = "银行流水A";// A录入银行流水数据
exgr.exchange(A);//同步点,交换数据
} catch (InterruptedException e) {
}
}
}); threadPool.execute(new Runnable() {
@Override
public void run() {
try {
String B = "银行流水B";// B录入银行流水数据
String A = exgr.exchange("B");//同步点,交换数据
System.out.println("A和B数据是否一致:" + A.equals(B) + "\nA录入的是:"+ A + "\nB录入的是:" + B);
} catch (InterruptedException e) {
}
}
}); threadPool.shutdown();
}

运行结果:

A和B数据是否一致:false

A录入的是:银行流水A

B录入的是:银行流水B

文献:

  • 《java并发编程的艺术》

并发工具类(四)线程间的交换数据 Exchanger的更多相关文章

  1. Java并发工具类之线程间数据交换工具Exchanger

    Exchanger是一个用于线程间协做的工具类,主要用于线程间的数据交换.它提供了一个同步点,在这个同步点,两个线程可以彼此交换数据.两个线程通过exchange方法交换数据,如果一个线程执行exch ...

  2. Java并发编程-并发工具类及线程池

    JUC中提供了几个比较常用的并发工具类,比如CountDownLatch.CyclicBarrier.Semaphore. CountDownLatch: countdownlatch是一个同步工具类 ...

  3. Java中的并发工具类(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)

    在JDK的并发包里提供了很多有意思的并发工具类.CountDownLatch.CyclicBarrier和Semaphore 工具类提供了一种并发流程控制的手段,Exchanger 工具类则提供了在线 ...

  4. Java 并发工具类 CountDownLatch、CyclicBarrier、Semaphore、Exchanger

    本文部分摘自<Java 并发编程的艺术> CountDownLatch CountDownLatch 允许一个或多个线程等待其他线程完成操作.假设现有一个需求:我们需要解析一个 Excel ...

  5. Java并发指南9:AQS共享模式与并发工具类的实现

    一行一行源码分析清楚 AbstractQueuedSynchronizer (三) 转自:https://javadoop.com/post/AbstractQueuedSynchronizer-3 ...

  6. Java线程的并发工具类

    Java线程的并发工具类. 一.fork/join 1. Fork-Join原理 在必要的情况下,将一个大任务,拆分(fork)成若干个小任务,然后再将一个个小任务的结果进行汇总(join). 适用场 ...

  7. 并发工具类(三)控制并发线程的数量 Semphore

    前言   JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...

  8. Java并发(十四):并发工具类——CountDownLatch

    先做总结: 1.CountDownLatch 是什么? CountDownLatch 允许一个或多个线程等待其他线程(不一定是线程,某个操作)完成之后再执行. CountDownLatch的构造函数接 ...

  9. Java并发编程系列-(2) 线程的并发工具类

    2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...

随机推荐

  1. OK335xS canutils deal with compile error

    /************************************************************************************** * OK335xS ca ...

  2. 【机器学习算法】cascade classifier级联分类器

    前言 参考 1.级联分类器: 完

  3. No.02——第一次使用Android Studio,并创建出Hello World

    1.第一次打开Studio 2.点击创建新项目 然后填上相关信息,注意在Company Domain(公司域名)地方的填写,不同于Eclipse对应实际电脑中文件夹,而是在你所选择的Project文件 ...

  4. Unity 3D游戏-贪吃蛇类游戏源码:重要方法和功能的实现

    贪吃蛇类游戏源码 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 头部移动方式 2 生成 Shit 道具 ...

  5. null 与 undefinded

    null表示"没有对象",即该处不应该有值.典型用法是: (1) 作为函数的参数,表示该函数的参数不是对象. (2) 作为对象原型链的终点. Object.getPrototype ...

  6. 51Nod 1091:线段的重叠(贪心)

    1091 线段的重叠  基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 ...

  7. java二叉树排序实现

    原创:转载请注明出处 目的:想用java实现二叉树排序算法 思想:利用java中面向对象的思想,即: Tree:类 树根Tree:root //static所属于每一个Tree 左节点Tree:lef ...

  8. mysql 常用linux命令

    ★ 数据导出命令 D:\Program Files\MySQL\MySQL Server 5.6.39\bin 导出:  mysqldump -u root -p cela_sub > D:/d ...

  9. 调用飞信HTTP接口给自己发短信

    注: 1.下文中所有HTTP请求所指的Host都是f.10086.cn 2.目前只有中国移动用户可以使用 1.打开登录页面:GET /huc/user/space/login.do?m=submit& ...

  10. spring boot 项目文件结构

    启动类建议放在RootPackage的原因: 根据SpringBoot的内置实现,Spring默认从@ComponentScan注解所在的位置开始向后扫描,也就是说,只要我们将组件放在启动类所在的Ro ...