可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形式。

换句话说Exchanger提供的是一个交换服务,允许原子性的交换两个(多个)对象,但同时只有一对才会成功。先看一个简单的实例模型。

在上面的模型中,我们假定一个空的栈(Stack),栈顶(Top)当然是没有元素的。同时我们假定一个数据结构Node,包含一个要交换的元素E和一个要填充的“洞”Node。这时线程T1携带节点node1进入栈(cas_push),当然这是CAS操作,这样栈顶就不为空了。线程T2携带节点node2进入栈,发现栈里面已经有元素了node1,同时发现node1的hold(Node)为空,于是将自己(node2)填充到node1的hold中(cas_fill)。然后将元素node1从栈中弹出(cas_take)。这样线程T1就得到了node1.hold.item也就是node2的元素e2,线程T2就得到了node1.item也就是e1,从而达到了交换的目的。

算法描述就是下图展示的内容。

JDK 5就是采用类似的思想实现的Exchanger。JDK 6以后为了支持多线程多对象同时Exchanger了就进行了改造(为了支持更好的并发),采用ConcurrentHashMap的思想,将Stack分割成很多的片段(或者说插槽Slot),线程Id(Thread.getId())hash相同的落在同一个Slot上,这样在默认32个Slot上就有很好的吞吐量。当然会根据机器CPU内核的数量有一定的优化,有兴趣的可以去了解下Exchanger的源码。

至于Exchanger的使用,在JDK文档上有个例子,讲述的是两个线程交换数据缓冲区的例子(实际上仍然可以认为是生产者/消费者模型)。

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();
   }
  }

Exchanger实现的是一种数据分片的思想,这在大数据情况下将数据分成一定的片段并且多线程执行的情况下有一定的使用价值。

最近一直推托工作忙,更新频度越来越低了,好在现在的工作还有点个人时间,以后争取多更新下吧,至少也要把这个专辑写完。

深入浅出 Java Concurrency (26): 并发容器 part 11 Exchanger[转]的更多相关文章

  1. 《深入浅出 Java Concurrency》—并发容器 ConcurrentMap

    (转自:http://blog.csdn.net/fg2006/article/details/6404226) 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器 ...

  2. 深入浅出 Java Concurrency (21): 并发容器 part 6 可阻塞的BlockingQueue (1)[转]

    在<并发容器 part 4 并发队列与Queue简介>节中的类图中可以看到,对于Queue来说,BlockingQueue是主要的线程安全版本.这是一个可阻塞的版本,也就是允许添加/删除元 ...

  3. 深入浅出 Java Concurrency (16): 并发容器 part 1 ConcurrentMap (1)[转]

    从这一节开始正式进入并发容器的部分,来看看JDK 6带来了哪些并发容器. 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器,Collections.synchro ...

  4. 深入浅出 Java Concurrency (27): 并发容器 part 12 线程安全的List/Set[转]

    本小节是<并发容器>的最后一部分,这一个小节描述的是针对List/Set接口的一个线程版本. 在<并发队列与Queue简介>中介绍了并发容器的一个概括,主要描述的是Queue的 ...

  5. 深入浅出 Java Concurrency (17): 并发容器 part 2 ConcurrentMap (2)[转]

    本来想比较全面和深入的谈谈ConcurrentHashMap的,发现网上有很多对HashMap和ConcurrentHashMap分析的文章,因此本小节尽可能的分析其中的细节,少一点理论的东西,多谈谈 ...

  6. 深入浅出 Java Concurrency (25): 并发容器 part 10 双向并发阻塞队列 BlockingDeque[转]

    这个小节介绍Queue的最后一个工具,也是最强大的一个工具.从名称上就可以看到此工具的特点:双向并发阻塞队列.所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条 ...

  7. 深入浅出 Java Concurrency (23): 并发容器 part 8 可阻塞的BlockingQueue (3)[转]

    在Set中有一个排序的集合SortedSet,用来保存按照自然顺序排列的对象.Queue中同样引入了一个支持排序的FIFO模型. 并发队列与Queue简介 中介绍了,PriorityQueue和Pri ...

  8. 深入浅出 Java Concurrency (20): 并发容器 part 5 ConcurrentLinkedQueue[转]

    ConcurrentLinkedQueue是Queue的一个线程安全实现.先来看一段文档说明. 一个基于链接节点的无界线程安全队列.此队列按照 FIFO(先进先出)原则对元素进行排序.队列的头部 是队 ...

  9. 深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介[转]

    Queue是JDK 5以后引入的新的集合类,它属于Java Collections Framework的成员,在Collection集合中和List/Set是同一级别的接口.通常来讲Queue描述的是 ...

随机推荐

  1. linux使用nmon监控、分析系统性能

    linux使用nmon监控.分析系统性能   一.概述 nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具,相对于其它一些系统资源监控工具来说,nmon所记录的信息是比较全面的, ...

  2. 16-Ubuntu-文件和目录命令-切换目录-cd

    cd(change directory),其功能为更改当前的工作目录. 注意:Linux所有的目录和文件名都是大小写敏感的. 命令 含义 cd     切换到当前用户的主目录(/home/用户目录) ...

  3. C 二维数组与指针

    http://c.biancheng.net/view/2022.html 1. 区分指针数组和数组指针 指针数组:存放指针的数组,如 int *pstr[5] = NULL; 数组中每个元素存放的是 ...

  4. OpenCV-Python Tutorials目录

    版本 3.4.6 1 Introduction to OpenCV OpenCV介绍Learn how to setup OpenCV-Python on your computer! 2 Gui F ...

  5. ionic js 滑动框ion-slide-box 滑动框是一个包含多页容器的组件,每页滑动或拖动切换

    ionic 滑动框 ion-slide-box 滑动框是一个包含多页容器的组件,每页滑动或拖动切换: 效果图如下: 用法 <ion-slide-box on-slide-changed=&quo ...

  6. Error: Cannot find module '@babel/core'

    报错如下 产生原因 babel-loader和babel-core版本不对应所产生的, babel-loader 8.x对应babel-core 7.x babel-loader 7.x对应babel ...

  7. Centos6 安装完之后,没有网络

    Virtualbox安装的centos 6.10的虚拟机,安装时,网络是NAT网络,安装完之后,将网络改为桥接网卡,启动虚拟机之后,使用 ifconfig 命令查看没有到eth0的信息,只有127.0 ...

  8. 2019亚太内容分发大会,阿里云获CDN领袖奖、技术突破奖

    近日,亚太CDN产业联盟主办的2019亚太内容分发大会在上海召开.本次大会以"5G分发"为主题,集结了CDN领域近千名行业领袖.专家参与.在会上,阿里云斩获“CDN领袖奖”.“技术 ...

  9. 【转载】Delphi异常处理try except语句和try finally语句用法以及区别

    Delphi异常处理try except语句和try finally语句用法以及区别 一直写程序都没管他们,也尽量很少用,今天终于想把他给弄个明白,在网上找来,记下!主要是前面小部分,后面的是详细说明 ...

  10. day23_3_configparse

    #!/usr/bin/env python# -*- coding:utf-8 -*-# ------------------------------------------------------- ...