java并发编程-并发包工具:Exchanger使用及原理、案例源码

Exchanger

简介

​ Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的。

​ Exchanger类提供了两个方法,String exchange(V x):用于交换,启动交换并等待另一个线程调用exchange;String exchange(V x,long timeout,TimeUnit unit):用于交换,启动交换并等待另一个线程调用exchange,并且设置最大等待时间,当等待时间超过timeout便停止等待。

总结:

  • 交换的是数据的原生对象,可能存在线程安全问题
  • 如果一个成对线程到达了交换点,其他线程未到达,会等待
  • change方法总是成对的使用,不能出现更多的

案例1:exchange使用及延时

1、if the pair thread not reached change point,the thread will waiting.
2、use the change must be paired.

package com.ln.juc.utils.exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.juc.utils.exchanger
 * @Name:ExchangerExample1
 * @Author:linianest
 * @CreateTime:2021/1/17 11:18
 * @version:1.0
 * @Description TODO:
 */
public class ExchangerExample1 {
    /**
     * V r=exchange(V v)
     * v: indicate the object the current thread wanted transfer
     * r: indicate the other thread(pair) return object.
     *
     * <pre>
     *     NOTE:
     *          1、if thepair thread not reached change point,the thread will waiting.
     *          2、use the change must be paired.
     * </pre>
     *
     * @param args
     */
    public static void main(String[] args) {
        Runtime.getRuntime().availableProcessors();

        final Exchanger<String> exchanger = new Exchanger<>();

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start.");
            try {
//                String result = exchanger.exchange("i am come from T-A", 10, TimeUnit.SECONDS);
                String result = exchanger.exchange("i am come from T-A", 2, TimeUnit.SECONDS);
                System.out.println(Thread.currentThread().getName() + " get value [" + result + "]");
            } catch (InterruptedException | TimeoutException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end.");
        }, "==A==").start();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start.");
            try {
                TimeUnit.SECONDS.sleep(13);
                String result = exchanger.exchange("i am come from T-B");
                System.out.println(Thread.currentThread().getName() + " get value [" + result + "]");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end.");
        }, "==B==").start();
    }
}

Exchanger 发送的是原生对象,不是拷贝对象

package com.ln.juc.utils.exchanger;

import java.util.concurrent.Exchanger;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.juc.utils.exchanger
 * @Name:ExchangerExample2
 * @Author:linianest
 * @CreateTime:2021/1/17 11:48
 * @version:1.0
 * @Description TODO: Exchanger 发送的是原生对象,不是拷贝对象
 */
public class ExchangerExample3 {
    public static void main(String[] args) {
        final Exchanger<Object> exchanger = new Exchanger<>();
        new Thread(()->{
            Object obj = new Object();
            System.out.println("A will send the object "+obj);
            try {
                Object result = exchanger.exchange(obj);
                System.out.println("A get the object "+result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"==A==").start();
        new Thread(()->{
             Object obj = new Object();
            System.out.println("B will send the object "+obj);
            try {
                Object result = exchanger.exchange(obj);
                System.out.println("B get the object "+result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"==B==").start();
    }
}

案例2:循环调用

package com.ln.juc.utils.exchanger;

import com.ln.juc.atomic.AtomicInteger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.juc.utils.exchanger
 * @Name:ExchangerExample2
 * @Author:linianest
 * @CreateTime:2021/1/17 11:48
 * @version:1.0
 * @Description TODO: Exchanger的重复循环调用
 */
public class ExchangerExample3 {
    public static void main(String[] args) {
        final Exchanger<Integer> exchanger = new Exchanger<>();
        new Thread(() -> {
            AtomicReference<Integer> value = new AtomicReference<Integer>(1);
            try {
                while (true) {
                    value.set(exchanger.exchange(value.get()));
                    System.out.println("A get the value " + value);
                    TimeUnit.SECONDS.sleep(3);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "==A==").start();
        new Thread(() -> {
            AtomicReference<Integer> value = new AtomicReference<Integer>(2);
            try {
                while (true) {
                    value.set(exchanger.exchange(value.get()));
                    System.out.println("B get the value " + value);
                    TimeUnit.SECONDS.sleep(2);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "==B==").start();

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值