JUC学习之Exchanger

Stella981
• 阅读 640

直接看代码吧

package exchange;

import java.util.concurrent.Exchanger;

/**
 * Exchanger让两个线程可以互换信息。
 * 例子中服务生线程往空的杯子里倒水,顾客线程从装满水的杯子里喝水,
 * 然后通过Exchanger双方互换杯子,服务生接着往空杯子里倒水,顾客接着喝水,
 * 然后交换,如此周而复始。
 */
public class ExchangerTest {

    // 描述一个装水的杯子
    public static class Cup{
        // 标识杯子是否有水
        private boolean full = false;
        public Cup(boolean full){
            this.full = full;
        }
        // 添水,假设需要5s
        public void addWater(){
            if (!this.full){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                this.full = true;
            }
        }
        // 喝水,假设需要10s
        public void drinkWater(){
            if (this.full){
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                }
                this.full = false;
            }
        }
    }
    
    public static void testExchanger() {
        //    初始化一个Exchanger,并规定可交换的信息类型是杯子
        final Exchanger<Cup> exchanger = new Exchanger<Cup>();
        // 初始化一个空的杯子和装满水的杯子
        final Cup initialEmptyCup = new Cup(false); 
        final Cup initialFullCup = new Cup(true);

        //服务生线程
        class Waiter implements Runnable {
            public void run() {
                Cup currentCup = initialEmptyCup;
                try {
                    int i=0;
                    while (i < 2){
                        System.out.println("服务生开始往杯子中添水:"
                                + System.currentTimeMillis());
                        // 往空的杯子里加水
                        currentCup.addWater();
                        System.out.println("服务生添水完毕:"
                                + System.currentTimeMillis());
                        // 杯子满后和顾客的空杯子交换
                        System.out.println("服务生等待与顾客交换杯子:"
                                + System.currentTimeMillis());
                        currentCup = exchanger.exchange(currentCup);
                        System.out.println("服务生与顾客交换杯子完毕:"
                                + System.currentTimeMillis());
                        i++;
                    }

                } catch (InterruptedException ex) {
                }
            }
        }

        //顾客线程
        class Customer implements Runnable {
            public void run() {
                Cup currentCup = initialFullCup;
                try {
                    int i=0;
                    while (i < 2){
                        System.out.println("顾客开始喝水:"
                                + System.currentTimeMillis());
                        //把杯子里的水喝掉
                        currentCup.drinkWater();
                        System.out.println("顾客喝水完毕:"
                                + System.currentTimeMillis());
                        //将空杯子和服务生的满杯子交换
                        System.out.println("顾客等待与服务生交换杯子:"
                                + System.currentTimeMillis());
                        currentCup = exchanger.exchange(currentCup);
                        System.out.println("顾客与服务生交换杯子完毕:"
                                + System.currentTimeMillis());
                        i++;
                    }
                } catch (InterruptedException ex) {
                }
            }
        }
        
        new Thread(new Waiter()).start();
        new Thread(new Customer()).start();
    }
    
    public static void main(String[] args) {
        ExchangerTest.testExchanger();
    }
}
点赞
收藏
评论区
推荐文章
遇见这么刁钻的面试题怎么办???Java怎么利用线程工厂监控线程池
@(https://shimo.im/docs/9GTP6XrJg9J88cJD/)明人不说暗话,直接开撸代码!!!ThreadFactory线程池中的线程从哪里来呢?就是ThreadFoctorycpublicinterfaceThreadFactoryThreadnewThread(Runnabler);Threadfactory里
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
3年前
Android视频直播流(三) YUV 数据的存储,以及播放
上一章写了YUV数据的获取,这里写写怎么把YUV数据保存起来,以及播放吧。因为YUV数据,都是从camera的回调里拿到的,所以不可以对回调进行阻塞,所以最好的处理方式就是:定义一个队列,在camera的回调里只管往队列里塞数据,在外部,用一个线程,死循环,利用队列的特性:有
Wesley13 Wesley13
3年前
Java线程同步之一
一、线程同步线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序。同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务。每个服务员在同一时刻只能接待一个顾客的点餐,那么除了正在接待的顾客,其他人只能等待排队。当一个点餐服务完成之后,其他顾客就可以上去进行点餐。从这个例子中可以看到如下几个关注点:点餐服务
Easter79 Easter79
3年前
ThreadLocal 详解
概念ThreadLocal用于提供线程局部变量,在多线程环境可以保证各个线程里的变量独立于其它线程里的变量。也就是说ThreadLocal可以为每个线程创建一个【单独的变量副本】,相当于线程的privatestatic类型变量。使用示例publicclassThreadLocalTest{
Wesley13 Wesley13
3年前
Java并发新构件之Exchanger
    Exchanger是在两个任务之间交换对象的栅栏。当两个任务进入栅栏时,它们各自拥有一个对象,当它们离开时,它们都拥有对方的对象。Exchanger的典型应用场景是:一个任务在创建对象,而这些对象的生产代价很高,另一个任务在消费这些对象。通过这种方式,可以有更多的对象在被创建的同时被消费。    为了演示Exchanger类,我们将创建生产者
Stella981 Stella981
3年前
Exchange 应用1
importjava.util.concurrent.Exchanger;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.TimeUnit;
Wesley13 Wesley13
3年前
C++并发与多线程学习笔记
condition\_variablewait()notify\_onenotify\_allcondition\_variable条件变量的实际用途:比如有两个线程A和B,在线程A中等待一个条件满足,(消息队列中有要处理的消息),线程B专门往队列中丢数据。当B往线程中放入数据,同时B通
Wesley13 Wesley13
3年前
Java 内存模型基础
一、并发编程模型的两个关键问题1\.线程之间如何通信通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。在共享内存的并发模型里,线程之间共享程序的公共状态,通过写读内存中的公共状态进行隐式通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息来显式