写在前面

  前面三篇博客分别介绍了CyclicBarrier、CountDownLatch、Semaphore,现在介绍并发工具类中的最后一个Exchange。Exchange是最简单的也是最复杂的,简单在于API非常简单,就一个构造方法和两个exchange()方法,最复杂在于它的实现是最复杂的(本文不解释。太复杂)

  在API是这么介绍的:可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。

  Exchanger,它允许在并发任务之间交换数据。具体来说,Exchanger类允许在两个线程之间定义同步点。当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中。

应用示例

public class ExchangerTest {

    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) + ",A录入的是:"
+ A + ",B录入是:" + B);
} catch (InterruptedException e) {
}
}
}); threadPool.shutdown(); }
}

示例2

public class ExchangerTest {
static class Producer implements Runnable{
//生产者、消费者交换的数据结构
private List<String> buffer;
//步生产者和消费者的交换对象
private Exchanger<List<String>> exchanger;
Producer(List<String> buffer,Exchanger<List<String>> exchanger){
this.buffer = buffer;
this.exchanger = exchanger;
}
@Override
public void run() {
for(int i = 1 ; i < 5 ; i++){
System.out.println("生产者第" + i + "次提供");
for(int j = 1 ; j <= 3 ; j++){
System.out.println("生产者装入" + i + "--" + j);
buffer.add("buffer:" + i + "--" + j);
}
System.out.println("生产者装满,等待与消费者交换...");
try {
exchanger.exchange(buffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} static class Consumer implements Runnable {
private List<String> buffer;
private final Exchanger<List<String>> exchanger;
public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) {
this.buffer = buffer;
this.exchanger = exchanger;
}
@Override
public void run() {
for (int i = 1; i < 5; i++) {
//调用exchange()与消费者进行数据交换
try {
buffer = exchanger.exchange(buffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者第" + i + "次提取");
for (int j = 1; j <= 3 ; j++) {
System.out.println("消费者 : " + buffer.get(0));
buffer.remove(0);
}
}
}
}
public static void main(String[] args){
List<String> buffer1 = new ArrayList<String>();
List<String> buffer2 = new ArrayList<String>();
Exchanger<List<String>> exchanger = new Exchanger<List<String>>(); Thread producerThread = new Thread(new Producer(buffer1,exchanger));
Thread consumerThread = new Thread(new Consumer(buffer2,exchanger));
producerThread.start();
consumerThread.start();
}
}
生产者第1次提供
生产者装入1--
生产者装入1--
生产者装入1--
生产者装满,等待与消费者交换...
生产者第2次提供
消费者第1次提取
生产者装入2--
消费者 : buffer:--
生产者装入2--
生产者装入2--
生产者装满,等待与消费者交换...
消费者 : buffer:--
消费者 : buffer:--
消费者第2次提取
消费者 : buffer:--
消费者 : buffer:--
消费者 : buffer:--
生产者第3次提供
生产者装入3--
生产者装入3--
生产者装入3--
生产者装满,等待与消费者交换...
生产者第4次提供
生产者装入4--
生产者装入4--
生产者装入4--
生产者装满,等待与消费者交换...
消费者第3次提取
消费者 : buffer:--
消费者 : buffer:--
消费者 : buffer:--
消费者第4次提取
消费者 : buffer:--
消费者 : buffer:--
消费者 : buffer:--

j.u.c系列(11)---之并发工具类:Exchanger的更多相关文章

  1. Java并发(十六):并发工具类——Exchanger

    Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数 ...

  2. Java多线程并发工具类-信号量Semaphore对象讲解

    Java多线程并发工具类-Semaphore对象讲解 通过前面的学习,我们已经知道了Java多线程并发场景中使用比较多的两个工具类:做加法的CycliBarrier对象以及做减法的CountDownL ...

  3. j.u.c系列(08)---之并发工具类:CountDownLatch

    写在前面 CountDownLatch所描述的是”在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待“:用给定的计数 初始化 CountDownLatch.由于调用了 countDo ...

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

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

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

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

  6. 并发工具类(五) Phaser类

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

  7. Java并发(十五):并发工具类——信号量Semaphore

    先做总结: 1.Semaphore是什么? Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源. 把它比作是控制流量的红绿灯,比如XX马路要 ...

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

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

  9. Java并发(十三):并发工具类——同步屏障CyclicBarrier

    先做总结 1.CyclicBarrier 是什么? CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点) ...

随机推荐

  1. Java SpringMVC框架学习(三)springMVC的执行流程

    具体执行逻辑如下: 浏览器提交请求到中央调度器. 中央调度器将请求转给处理器映射器. 处理器映射器根据请求, 找到请求对应的处理器, 并将其封装为处理器执行链返回给中央调度器. 中央调度器根据处理器执 ...

  2. XHR工厂的实现

    ajax这种常见的开发模式已经遍布我们日常的开发之中了,ajax本质还是采用一种轮询的模式,就是隔一段时间去发送一次http请求,获取数据,然后显示在页面之上,当然,ajax比起新兴的WebScoke ...

  3. mysqldump只导出表结构或只导出数据的实现方法【转】

    mysql mysqldump 只导出表结构 不导出数据 mysqldump --opt -d 数据库名 -u root -p > xxx.sql 备份数据库 #mysqldump 数据库名 & ...

  4. 数组slice方法

    slice slice(start,end):方法可从已有数组中返回选定的元素,返回一个新数组,包含从start到end(不包含该元素)的数组元素.(不会改变原数组) start参数:必须,规定从何处 ...

  5. django之class Meta

    通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(models.Model): bar = models.CharFi ...

  6. Node.js模块定义总结

    为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统.模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的.换言之,一个 Node.js 文件就是一个模块,这 ...

  7. 织梦任意页面调用{dede:field.content/}的方法

    过滤掉所有的html代码,只显示文字,具体的ID自己更改. 代码如下: {dede:sql sql='Select content from dede_arctype where id=1'} [fi ...

  8. Java编程的逻辑 (28) - 剖析包装类 (下)

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  9. Redis学习笔记9--Redis持久化

    redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.redis支持四种持久化方式,一是 Snapshotting(快照)也是默认方式:二是Appen ...

  10. PocketMoney

    PocketMoney( Money.pas/cpp/c)Description学校为了表彰tsoi的优异成绩, m个领导每人都决定给tsoi的一些人发一些小红包.于是n个Tsoier排成一排,等待着 ...