如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到 Exchanger 这个类,Exchanger 为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步点,只有当每个线程都在进入 exchange() 方法并给出对象时,才能接受其他线程返回时给出的对象。

每次只能两个线程交换数据,如果有多个线程,也只有两个能交换数据。下面看个通俗的例子:一手交钱一首交货!

  1. public class ExchangerTest {

  2.    public static void main(String[] args) {

  3.        ExecutorService service = Executors.newCachedThreadPool();

  4.        final Exchanger exchanger = new Exchanger(); //定义一个交换对象,用来交换数据      

  5.        //开启一个线程执行任务

  6.        service.execute(new Runnable(){            

  7.            @Override

  8.            public void run() {

  9.                try {                

  10.                    String data1 = "海洛因";

  11.                    System.out.println("线程" + Thread.currentThread().getName()

  12.                            + "正在把毒品" + data1 + "拿出来");                    

  13.                    Thread.sleep((long)(Math.random()*10000));

  14.                  //把要交换的数据传到exchange方法中,然后被阻塞,等待另一个线程与之交换。返回交换后的数据

  15.                    String data2 = (String)exchanger.exchange(data1);

  16.                    System.out.println("线程" + Thread.currentThread().getName() +  

  17.                    "用海洛因换来了" + data2);

  18.                }catch(Exception e){    

  19.                } finally {

  20.                    service.shutdown();

  21.                    System.out.println("交易完毕,拿着钱快跑!");

  22.                }

  23.            }    

  24.        });

  25.        //开启另一个线程执行任务

  26.        service.execute(new Runnable(){            

  27.            @Override

  28.            public void run() {

  29.                try {                

  30.                    String data1 = "300万";

  31.                    System.out.println("线程" + Thread.currentThread().getName() +  

  32.                    "正在把" + data1 +"拿出来");

  33.                    Thread.sleep((long)(Math.random()*10000));                      

  34.                    String data2 = (String)exchanger.exchange(data1);                    

  35.                    System.out.println("线程" + Thread.currentThread().getName() +  

  36.                    "用300万弄到了" + data2);

  37.                }catch(Exception e){    

  38.                } finally {

  39.                    service.shutdown();

  40.                    System.out.println("交易完毕,拿着海洛因快跑!");

  41.                }

  42.            }    

  43.        });        

  44.    }

  45. }

从代码中我仿佛看到了两个人在交易毒品的场面……来看一下交易结果如何:

线程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() 方法并给出对象时,才能接受其他线程返回时给出的对象。

每次只能两个线程交换数据,如果有多个线程,也只有两个能交换数据。下面看个通俗的例子:一手交钱一首交货!

  1. public class ExchangerTest {

  2.    public static void main(String[] args) {

  3.        ExecutorService service = Executors.newCachedThreadPool();

  4.        final Exchanger exchanger = new Exchanger(); //定义一个交换对象,用来交换数据      

  5.        //开启一个线程执行任务

  6.        service.execute(new Runnable(){            

  7.            @Override

  8.            public void run() {

  9.                try {                

  10.                    String data1 = "海洛因";

  11.                    System.out.println("线程" + Thread.currentThread().getName()

  12.                            + "正在把毒品" + data1 + "拿出来");                    

  13.                    Thread.sleep((long)(Math.random()*10000));

  14.                  //把要交换的数据传到exchange方法中,然后被阻塞,等待另一个线程与之交换。返回交换后的数据

  15.                    String data2 = (String)exchanger.exchange(data1);

  16.                    System.out.println("线程" + Thread.currentThread().getName() +  

  17.                    "用海洛因换来了" + data2);

  18.                }catch(Exception e){    

  19.                } finally {

  20.                    service.shutdown();

  21.                    System.out.println("交易完毕,拿着钱快跑!");

  22.                }

  23.            }    

  24.        });

  25.        //开启另一个线程执行任务

  26.        service.execute(new Runnable(){            

  27.            @Override

  28.            public void run() {

  29.                try {                

  30.                    String data1 = "300万";

  31.                    System.out.println("线程" + Thread.currentThread().getName() +  

  32.                    "正在把" + data1 +"拿出来");

  33.                    Thread.sleep((long)(Math.random()*10000));                      

  34.                    String data2 = (String)exchanger.exchange(data1);                    

  35.                    System.out.println("线程" + Thread.currentThread().getName() +  

  36.                    "用300万弄到了" + data2);

  37.                }catch(Exception e){    

  38.                } finally {

  39.                    service.shutdown();

  40.                    System.out.println("交易完毕,拿着海洛因快跑!");

  41.                }

  42.            }    

  43.        });        

  44.    }

  45. }

从代码中我仿佛看到了两个人在交易毒品的场面……来看一下交易结果如何:

线程pool-1-thread-1正在把毒品海洛因拿出来

线程pool-1-thread-2正在把300万拿出来

线程pool-1-thread-2用300万弄到了海洛因

线程pool-1-thread-1用海洛因换来了300万

交易完毕,拿着海洛因快跑!

交易完毕,拿着钱快跑!

跑的倒是快,从运行结果来看,确实实现了数据的交换,这个只是交换一个基本类型的数据而已,它真正的用处不仅仅局限于此,比如我们可以交换一个对象,这就有用了,JDK 官方提到了一个高级的应用:

使用 Exchanger 在线程间交换缓冲区,因此,在需要时,填充缓冲区的线程获取一个新腾空的缓冲区,并将填满的缓冲区传递给腾空缓冲区的线程。

这就得根据实际情况了,思想和上面的一样,实际中肯定要定义一个缓冲区的类,然后两个线程之间交换的就是这个缓冲区的类即可,至于类中如何实现,就得看实际情况了。Exchanger 的使用就总结这么多吧~

作者:华为云云享专家倪升武

【并发技术16】线程同步工具Exchanger的使用的更多相关文章

  1. 线程同步工具 Semaphore类使用案例

    参考博文 : 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 使用Semaphore模拟互斥锁 当一个线程想要访问某个共享资源,首先,它 ...

  2. 线程同步工具 Semaphore类的基础使用

    推荐好文: 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 简介 Semaphore是基于计数的信号量,可以用来控制同时访问特定资源的线 ...

  3. Java核心知识点学习----线程同步工具类,CyclicBarrier学习

    线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...

  4. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  5. 同步工具——Exchanger

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文是转载文章,原文请见这里 一.Exchanger简介 ...

  6. 并发编程之 线程协作工具 LockSupport

    前言 在前面的文章中,我们介绍了并发工具中的4个,Samephore,CyclicBarrier,CountDownLatch,Exchanger,但是我们漏了一个,非常的好用的工具,楼主在这里必须加 ...

  7. Java提高班(三)并发中的线程同步与锁

    乐观锁.悲观锁.公平锁.自旋锁.偏向锁.轻量级锁.重量级锁.锁膨胀...难理解?不存的!来,话不多说,带你飙车. 上一篇介绍了线程池的使用,在享受线程池带给我们的性能优势之外,似乎也带来了另一个问题: ...

  8. java并发编程:线程同步和锁

    一.锁的原理 java中每个对象都有一个内置锁.当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this)有关的锁.获得一个对象的锁也称为获取锁,当程序运 ...

  9. C++并发编成 03 线程同步

    这一节主要讲讲线程同步的方式,C++ 11中提供了丰富的线程同步元语,如condition_variable,futrue,std::packaged_task<>,std::promis ...

随机推荐

  1. Python 基础之socket编程(一)

    Python 基础之socket编程(一) 可以进行通信玩儿了,感觉不错不错,网络通信就像打电话,我说一句你听一句之后,你再说一句,我听一句,就这样.....下去了.不扯淡了,来来来,看看今天都搞了点 ...

  2. 反射与泛型--使用泛型反射API打印出给定类的所有内容

    package chapter8Demos; import java.lang.reflect.*; import java.util.Arrays; import java.util.Scanner ...

  3. java中线程同步的几种方法

    1.使用synchronized关键字 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注: synchro ...

  4. .NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端

    .NET Core love gRPC 千呼万唤的 .NET Core 3.0 终于在 9 月份正式发布,在它的众多新特性中,除了性能得到了大大提高,比较受关注的应该是 ASP.NET Core 3. ...

  5. Excel的常用函数

    1.查找重复内容=IF(COUNTIF(A:A,A2)>1,"重复","") 2.重复内容首次出现时不提示=IF(COUNTIF(A$2:A2,A2)&g ...

  6. 护网杯2019 mergeheap --pwn

    护网 又是签到 一天 这道题一开始 不懂得如何泄露 libc 信息,就蒙了  后来群里师傅也是刚刚好 做出 到这里 我就接着做了 . 先看下保护,发现  全开了 然后 就看下流程 大概 就是添加  c ...

  7. python3 之 面向对象(类)、继承、派生和多态

    类提供了一种 组合数据和功能 的方法.创建一个新类意味着:创建一个新 类型  的对象,从而允许创建一个该类型的新 实例. 每个类的实例可以拥有: 保存自己状态的属性. 一个类的实例也可以有改变自己状态 ...

  8. kafka-manager新手安装入门指南

    Kafka-manager安装教程 使用环境 ubuntu18.04 Java 8 一.下载kafka 官网下载地址如下 https://www.apache.org/dyn/closer.cgi?p ...

  9. 今天是python专场UDP socket 链接

    type = SOCK_DGRAM UDP 协议的通信优势 允许一个服务器的同时和多个客户端通信 server import socket sk = socket.socket(type=socket ...

  10. Java中的Calendar 类和SimpleDateFormat 类

    1.Calendar 类:import java.util.Calendar;               Calendar cal = Calendar.getInstance();        ...