【并发技术16】线程同步工具Exchanger的使用
如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到 Exchanger 这个类,Exchanger 为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步点,只有当每个线程都在进入 exchange() 方法并给出对象时,才能接受其他线程返回时给出的对象。
每次只能两个线程交换数据,如果有多个线程,也只有两个能交换数据。下面看个通俗的例子:一手交钱一首交货!
public class ExchangerTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final Exchanger exchanger = new Exchanger(); //定义一个交换对象,用来交换数据//开启一个线程执行任务service.execute(new Runnable(){@Overridepublic void run() {try {String data1 = "海洛因";System.out.println("线程" + Thread.currentThread().getName()+ "正在把毒品" + data1 + "拿出来");Thread.sleep((long)(Math.random()*10000));//把要交换的数据传到exchange方法中,然后被阻塞,等待另一个线程与之交换。返回交换后的数据String data2 = (String)exchanger.exchange(data1);System.out.println("线程" + Thread.currentThread().getName() +"用海洛因换来了" + data2);}catch(Exception e){} finally {service.shutdown();System.out.println("交易完毕,拿着钱快跑!");}}});//开启另一个线程执行任务service.execute(new Runnable(){@Overridepublic void run() {try {String data1 = "300万";System.out.println("线程" + Thread.currentThread().getName() +"正在把" + data1 +"拿出来");Thread.sleep((long)(Math.random()*10000));String data2 = (String)exchanger.exchange(data1);System.out.println("线程" + Thread.currentThread().getName() +"用300万弄到了" + data2);}catch(Exception e){} finally {service.shutdown();System.out.println("交易完毕,拿着海洛因快跑!");}}});}}
从代码中我仿佛看到了两个人在交易毒品的场面……来看一下交易结果如何:
线程pool-1-thread-1正在把毒品海洛因拿出来
线程pool-1-thread-2正在把300万拿出来
线程pool-1-thread-2用300万弄到了海洛因
线程pool-1-thread-1用海洛因换来了300万
交易完毕,拿着海洛因快跑!
交易完毕,拿着钱快跑!
跑的倒是快,从运行结果来看,确实实现了数据的交换,这个只是交换一个基本类型的数据而已,它真正的用处不仅仅局限于此,比如我们可以交换一个对象,这就有用了,JDK 官方提到了一个高级的应用:
使用 Exchanger 在线程间交换缓冲区,因此,在需要时,填充缓冲区的线程获取一个新腾空的缓冲区,并将填满的缓冲区传递给腾空缓冲区的线程。
这就得根据实际情况了,思想和上面的一样,实际中肯定要定义一个缓冲区的类,然后两个线程之间交换的就是这个缓冲区的类即可,至于类中如何实现,就得看实际情况了。Exchanger 的使用就总结这么多吧~
如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到 Exchanger 这个类,Exchanger 为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步点,只有当每个线程都在进入 exchange() 方法并给出对象时,才能接受其他线程返回时给出的对象。
每次只能两个线程交换数据,如果有多个线程,也只有两个能交换数据。下面看个通俗的例子:一手交钱一首交货!
public class ExchangerTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final Exchanger exchanger = new Exchanger(); //定义一个交换对象,用来交换数据//开启一个线程执行任务service.execute(new Runnable(){@Overridepublic void run() {try {String data1 = "海洛因";System.out.println("线程" + Thread.currentThread().getName()+ "正在把毒品" + data1 + "拿出来");Thread.sleep((long)(Math.random()*10000));//把要交换的数据传到exchange方法中,然后被阻塞,等待另一个线程与之交换。返回交换后的数据String data2 = (String)exchanger.exchange(data1);System.out.println("线程" + Thread.currentThread().getName() +"用海洛因换来了" + data2);}catch(Exception e){} finally {service.shutdown();System.out.println("交易完毕,拿着钱快跑!");}}});//开启另一个线程执行任务service.execute(new Runnable(){@Overridepublic void run() {try {String data1 = "300万";System.out.println("线程" + Thread.currentThread().getName() +"正在把" + data1 +"拿出来");Thread.sleep((long)(Math.random()*10000));String data2 = (String)exchanger.exchange(data1);System.out.println("线程" + Thread.currentThread().getName() +"用300万弄到了" + data2);}catch(Exception e){} finally {service.shutdown();System.out.println("交易完毕,拿着海洛因快跑!");}}});}}
从代码中我仿佛看到了两个人在交易毒品的场面……来看一下交易结果如何:
线程pool-1-thread-1正在把毒品海洛因拿出来
线程pool-1-thread-2正在把300万拿出来
线程pool-1-thread-2用300万弄到了海洛因
线程pool-1-thread-1用海洛因换来了300万
交易完毕,拿着海洛因快跑!
交易完毕,拿着钱快跑!
跑的倒是快,从运行结果来看,确实实现了数据的交换,这个只是交换一个基本类型的数据而已,它真正的用处不仅仅局限于此,比如我们可以交换一个对象,这就有用了,JDK 官方提到了一个高级的应用:
使用 Exchanger 在线程间交换缓冲区,因此,在需要时,填充缓冲区的线程获取一个新腾空的缓冲区,并将填满的缓冲区传递给腾空缓冲区的线程。
这就得根据实际情况了,思想和上面的一样,实际中肯定要定义一个缓冲区的类,然后两个线程之间交换的就是这个缓冲区的类即可,至于类中如何实现,就得看实际情况了。Exchanger 的使用就总结这么多吧~
作者:华为云云享专家倪升武
【并发技术16】线程同步工具Exchanger的使用的更多相关文章
- 线程同步工具 Semaphore类使用案例
参考博文 : 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 使用Semaphore模拟互斥锁 当一个线程想要访问某个共享资源,首先,它 ...
- 线程同步工具 Semaphore类的基础使用
推荐好文: 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 简介 Semaphore是基于计数的信号量,可以用来控制同时访问特定资源的线 ...
- Java核心知识点学习----线程同步工具类,CyclicBarrier学习
线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...
- Python并发编程-进程 线程 同步锁 线程死锁和递归锁
进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...
- 同步工具——Exchanger
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文是转载文章,原文请见这里 一.Exchanger简介 ...
- 并发编程之 线程协作工具 LockSupport
前言 在前面的文章中,我们介绍了并发工具中的4个,Samephore,CyclicBarrier,CountDownLatch,Exchanger,但是我们漏了一个,非常的好用的工具,楼主在这里必须加 ...
- Java提高班(三)并发中的线程同步与锁
乐观锁.悲观锁.公平锁.自旋锁.偏向锁.轻量级锁.重量级锁.锁膨胀...难理解?不存的!来,话不多说,带你飙车. 上一篇介绍了线程池的使用,在享受线程池带给我们的性能优势之外,似乎也带来了另一个问题: ...
- java并发编程:线程同步和锁
一.锁的原理 java中每个对象都有一个内置锁.当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this)有关的锁.获得一个对象的锁也称为获取锁,当程序运 ...
- C++并发编成 03 线程同步
这一节主要讲讲线程同步的方式,C++ 11中提供了丰富的线程同步元语,如condition_variable,futrue,std::packaged_task<>,std::promis ...
随机推荐
- Java描述设计模式(17):调停者模式
本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 在公司的日常安排中,通常划分多个部门,每个部门又会分为不同的小组,部门经理的一项核心工作就是协调部门小组之间的工作 ...
- 20190630A(贪心)
题目描述 约翰留下他的N只奶牛上山采木.他离开的时候,她们像往常一样悠闲地在草场里吃草.可是,当他回来的时候,他看到了一幕惨剧:牛们正躲在他的花园里,啃食着他心爱的美丽花朵!为了使接下来花朵的损失最小 ...
- Unix/Linux 从哪儿来?那些改变世界的人们...
昨天看文章时发现自己对 linux 操作系统不够了解,还记得 17 年时听过老师的一些课,对 linux 的历史有一点了解,不过当时并没有记录笔记,现在已经忘的差不多了. 这次从网上找资料,又重新看了 ...
- jquery获取input输入框中的值
如何用javascript获取input输入框中的值,js/jq通过name.id.class获取input输入框中的value 先准备一段 HTML <input type="tex ...
- php 下载图片并打包成Zip格式压缩包
前言:最近公司有个需要下载多个图片并打包成压缩包的需求,下面来看看具体是怎么做的 1.没什么说的,懒得说啥,直接看代码 /** * 下载图片并生成压缩包 * @param $data 图片数组,一维 ...
- day5-列表专区
list 列表.类li = [1, 12, 9, "age", ["88", ["19", 10], "方法"], &q ...
- java本地缓存
1.为什么要使用缓存 由于服务器.数据库.网络等资源有限,无法支撑越来越多的请求与计算量,所以将一部分数据放在缓存中,以此减小薄弱环节的计算量和请求流程. 网站中缓存的应用场景: 1:可 ...
- nowcoder 鹏
鹏 时间限制:C/C++ 2秒,其他语言4秒空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 化而为鸟,其名为鹏.鹏之背,不知其 ...
- 从最近面试聊聊我所感受的.net天花板
#0 前言 入职新公司没多久,闲来无事在博客园闲逛,看到园友分享的面试经历,正好自己这段时间面试找工作,也挺多感想的,干脆趁这个机会总结整理一下.博主13年开始实习,14年毕业.到现在也工作五六年了. ...
- 力扣(LeetCode)按奇偶排序数组II 个人题解
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数. 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数:当 A[i] 为偶数时, i 也是偶数. 你可以返回任何满足上述条件的数组 ...