文档章节

(十二)java多线程之Exchanger

天之妖星
 天之妖星
发布于 2017/05/08 14:24
字数 1978
阅读 2
收藏 0

本人邮箱: kco1989@qq.com
欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代码已经全部托管github有需要的同学自行下载

引言

今天我们讲最后一个同步工具类Exchanger,这个比较简单,就是让两个线程交换数据.

理论

Exchanger只有两个方法而已,而且两个还是一样的,只是参数不通而已
* exchange(V x) 跟另外一个线程交换数据x,如果另外一个线程的数据准备好,那么当前线程会立刻返回,并获得另外一个线程的数据;否则当前线程会进入等待状态
* V exchange(V x, long timeout, TimeUnit unit): 跟exchange,如果会有一个指定的超时时间,如果在等待时间超时了,而且还没有收到对方的数据的话,则会抛出TimeoutException异常

例子 有耐心的山治和路飞

看过海贼王的人都知道山治和路飞,山治是一个厨师,手艺那是杠杠的.路飞则是一个大胃王,超能吃.现在编写一个程序,让山治不断给路飞做食物,而路飞不断吃,吃完之后要对山治说感谢.ok,开始编码

  • 先编写一个Food食物类,这个比较简单,就是定义一些食物
public class Food {
    public final static String[] food = {
            "打边炉","奶味芦笋汤","糟片鸭","烤花揽桂鱼","苦中作乐","七星丸","鸭黄豆腐","贝丝扒菜胆","脆炒南瓜丝","龙凤双腿",
            //省略部分代码....
    };

    private static Random random = new Random();
    public static String getRandomFood(){
        return food[random.nextInt(food.length)];
    }
}
  • 之后编写山治做菜的类 ShanZhiRunnable
public class ShanZhiRunnable implements Runnable{
    Exchanger<String> exchanger;
    Random random = new Random();
    public ShanZhiRunnable(Exchanger<String> exchanger) {
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        while (true){
            try {
                String food = Food.getRandomFood();
                System.out.println("==>山治开始做 " + food);
                Thread.sleep(random.nextInt(500));
                System.out.println("==>山治把 " + food + " 给做好了,给路飞送过去");
                String exchange = exchanger.exchange(food);
                System.out.println("==>山治收到路飞的评语:" + exchange);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
  • 然后编写路飞吃饭的类 LuFeiRunnable
public class LuFeiRunnable implements Runnable{
    Exchanger<String> exchanger;
    Random random = new Random();
    public LuFeiRunnable(Exchanger<String> exchanger) {
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        String temp = "开吃啦...";
        while (true){
            try {
                String food = exchanger.exchange(temp);
                System.out.println("--->路飞拿到山治做的菜: " + food);
                Thread.sleep(random.nextInt(500));
                System.out.println("--->路飞吃完" + food);
                temp = food + "太好吃!太感谢山治了...";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 最后编写测试类 TestMain
public class TestMain {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        new Thread(new LuFeiRunnable(exchanger)).start();
        new Thread(new ShanZhiRunnable(exchanger)).start();
    }
}

运行结果如下,并截取部分输出

==>山治开始做 一品鲍鱼 ==>山治把 一品鲍鱼 给做好了,给路飞送过去 ==>山治收到路飞的评语:开吃啦... ==>山治开始做 芝麻肉丝 --->路飞拿到山治做的菜: 一品鲍鱼 ==>山治把 芝麻肉丝 给做好了,给路飞送过去 --->路飞吃完一品鲍鱼 --->路飞拿到山治做的菜: 芝麻肉丝 ==>山治收到路飞的评语:一品鲍鱼太好吃!太感谢山治了... ==>山治开始做 鸡蛋炒西红柿 --->路飞吃完芝麻肉丝 ==>山治把 鸡蛋炒西红柿 给做好了,给路飞送过去 ==>山治收到路飞的评语:芝麻肉丝太好吃!太感谢山治了... --->路飞拿到山治做的菜: 鸡蛋炒西红柿 ==>山治开始做 油豆腐镶肉 ==>山治把 油豆腐镶肉 给做好了,给路飞送过去 --->路飞吃完鸡蛋炒西红柿 --->路飞拿到山治做的菜: 油豆腐镶肉 ==>山治收到路飞的评语:鸡蛋炒西红柿太好吃!太感谢山治了... ==>山治开始做 梅菜蒸鱼尾 ==>山治把 梅菜蒸鱼尾 给做好了,给路飞送过去 --->路飞吃完油豆腐镶肉 ==>山治收到路飞的评语:油豆腐镶肉太好吃!太感谢山治了... ==>山治开始做 炸子鸡 --->路飞拿到山治做的菜: 梅菜蒸鱼尾 ==>山治把 炸子鸡 给做好了,给路飞送过去 --->路飞吃完梅菜蒸鱼尾 --->路飞拿到山治做的菜: 炸子鸡 ==>山治收到路飞的评语:梅菜蒸鱼尾太好吃!太感谢山治了... ==>山治开始做 翠竹粉蒸鱼 ==>山治把 翠竹粉蒸鱼 给做好了,给路飞送过去 --->路飞吃完炸子鸡 --->路飞拿到山治做的菜: 翠竹粉蒸鱼 ==>山治收到路飞的评语:炸子鸡太好吃!太感谢山治了... ==>山治开始做 风情羊柳 ==>山治把 风情羊柳 给做好了,给路飞送过去

例子2 没耐心的山治和路飞

现在假设他们俩都没有耐心,不想一直等一下

  • LuFeiRunnable修改为:
public class LuFeiRunnable implements Runnable{
    Exchanger<String> exchanger;
    Random random = new Random();
    public LuFeiRunnable(Exchanger<String> exchanger) {
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        String temp = "开吃啦...";
        while (true){
            try {
                String food = exchanger.exchange(temp, 300, TimeUnit.MILLISECONDS);
                System.out.println("--->路飞吃完" + food);
                temp = food + "太好吃!太感谢山治了...";
                Thread.sleep(random.nextInt(500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                System.out.println("--->路飞等的不耐烦了,不想等......开始喝起 东北风" );
            }
        }
    }
}
  • ShanZhiRunnable修改为
public class ShanZhiRunnable implements Runnable{
    Exchanger<String> exchanger;
    Random random = new Random();
    public ShanZhiRunnable(Exchanger<String> exchanger) {
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        while (true){
            String food = Food.getRandomFood();
            try {
                System.out.println("==>山治开始做 " + food);
                Thread.sleep(random.nextInt(500));
                System.out.println("==>山治把 " + food + " 给做好了,给路飞送过去");
                String exchange = exchanger.exchange(food, 300, TimeUnit.MILLISECONDS);
                System.out.println("==>山治收到路飞的评语:" + exchange);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                System.out.println("==>山治等的不耐烦了,不想等......,把 " + food + " 其他船员吃了");
            }
        }

    }
}

运行一下程序:

==>山治开始做 辣子肉丁
--->路飞等的不耐烦了,不想等......开始喝起 东北风
==>山治把 辣子肉丁 给做好了,给路飞送过去
==>山治收到路飞的评语:开吃啦...
==>山治开始做 砂锅三味
--->路飞吃完辣子肉丁
==>山治把 砂锅三味 给做好了,给路飞送过去
==>山治收到路飞的评语:辣子肉丁太好吃!太感谢山治了...
--->路飞吃完砂锅三味
==>山治开始做 甜椒肉丝
==>山治把 甜椒肉丝 给做好了,给路飞送过去
--->路飞吃完甜椒肉丝
==>山治收到路飞的评语:砂锅三味太好吃!太感谢山治了...
==>山治开始做 一品鲍鱼
==>山治把 一品鲍鱼 给做好了,给路飞送过去
==>山治等的不耐烦了,不想等......,把 一品鲍鱼 其他船员吃了
==>山治开始做 香酥凤腿
--->路飞等的不耐烦了,不想等......开始喝起 东北风
==>山治把 香酥凤腿 给做好了,给路飞送过去
==>山治收到路飞的评语:甜椒肉丝太好吃!太感谢山治了...
--->路飞吃完香酥凤腿
==>山治开始做 雪花片汤
==>山治把 雪花片汤 给做好了,给路飞送过去
--->路飞吃完雪花片汤
==>山治收到路飞的评语:香酥凤腿太好吃!太感谢山治了...
==>山治开始做 凤尾金鱼
==>山治把 凤尾金鱼 给做好了,给路飞送过去
==>山治收到路飞的评语:雪花片汤太好吃!太感谢山治了...
--->路飞吃完凤尾金鱼
==>山治开始做 三菇浸鱼云
--->路飞等的不耐烦了,不想等......开始喝起 东北风
==>山治把 三菇浸鱼云 给做好了,给路飞送过去
==>山治收到路飞的评语:凤尾金鱼太好吃!太感谢山治了...
--->路飞吃完三菇浸鱼云
==>山治开始做 辣子鸡丁
==>山治把 辣子鸡丁 给做好了,给路飞送过去
==>山治收到路飞的评语:三菇浸鱼云太好吃!太感谢山治了...
--->路飞吃完辣子鸡丁
==>山治开始做 梅干菜烧肉

通过以上两个例子,掌握Exchanger应该没有什么难度.好的,这篇就到这里.


打赏

如果觉得我的文章写的好的话,有钱就捧个钱场,没钱就给我点个赞
微信打赏2元支付宝打赏2元

© 著作权归作者所有

天之妖星
粉丝 1
博文 30
码字总数 58258
作品 0
深圳
高级程序员
私信 提问
【JDK源码分析】同步工具Exchanger,它内部实现原理你看懂了吗?

前言 Exchanger应该算并发包中工具使用相对少的,因为它主要用于线程之间交换数据,它的用法比较简单在不同线程之间使用exchange方法交换数据,但是内部实现比较巧妙,使用了unsafe的CAS原子...

编程SHA
2018/12/17
0
0
Java 使用 happen-before 规则实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的...

stateIs0
2018/01/20
0
0
Java多线程11 同步工具类Exchanger

Java多线程目录 1 Exchanger 介绍 前面分别介绍了CyclicBarrier、CountDownLatch、Semaphore,现在介绍并发工具类中的最后一个Exchange。 Exchanger 是一个用于线程间协作的工具类,Exchang...

香沙小熊
2018/12/03
0
0
JAVA基础再回首(三十)——JAVA基础再回首完美结束,感概万千!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52724939 JAVA基础再回首(三十)——JAVA基础再回首完美结束,感概万千! 经过了几...

Aduroidpc
2016/10/02
0
0
Java程序员从笨鸟到菜鸟全部博客目录【2012年十一月七日更新】

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188 大学上了一年半,接触java也一年半了,虽然中间也有其他东西的学习,但是还是以java为主路线,想想这一年半,...

长平狐
2012/11/12
103
0

没有更多内容

加载失败,请刷新页面

加载更多

rsync工具常用选项以及同步的两种方式

rsync -av /etc/passwd /tmp/1.txt #rsync的本机传输写法 rsync -av /tmp/1.txt 192.168.188.128:/tmp/2.txt #rsync的远程传输rsync格式rsync [OPTION] … SRC ......

林怡丰
今天
3
0
GatewayWorker 报错:stream_socket_server(): unable to connect to tcp://0.0.0.0:1238

GatewayWorker 报错:stream_socket_server(): unable to connect to tcp://0.0.0.0:1238 (Address already in use) 官方文档虽然有相同的问题,但是对我的问题没起作用…… 后面发现自己手贱...

wenzhizhong
昨天
3
0
REST接口

文章来源 https://zhuanlan.zhihu.com/p/28674721?group_id=886181549958119424 http://www.ruanyifeng.com/blog/2014/05/restful_api.html REST 对请求的约定 REST 用来规范应用如何在 HTTP......

Airship
昨天
5
0
Spring Cloud Config 统一配置中心

Spring Cloud Config 统一配置中心 一、统一配置中心 统一管理配置 通常,我们会使用配置文件来管理应用的配置。如一个 Spring Boot 的应用,可以将配置信息放在 application.yml 文件中,如...

非摩尔根
昨天
6
0
android ------ AAPT2 error: check logs for details解决方法

AAPT 是全称是 Android Asset Packaging Tool,它是构建 App,甚至是构建 Android 系统都必不可少的一个工具。它的作用是将所有资源文件压缩打包到Android APK 当中。我们在 Android SDK 目录...

切切歆语
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部