高并发编程之Exchanger工具类讲解

一、Exchanger介绍
①、Exchanger,并发工具类,用于线程间的数据交换。
②、两个线程,两个缓冲区,一个线程往一个缓冲区里面填数据,另一个线程从另一个缓冲区里面取数据。当填数据的线程将缓冲区填满时,或者取数据的线程将缓冲区里的数据取空时,就主动向对方发起交换缓冲区的动作,而交换的时机是,一个缓冲区满,另一个缓冲区空。

注意:使用Exchanger来对线程进行数据操作时,线程必须是成对的(线程数量为双数)。

二、介绍Exchanger两个重要方法
①、exchange(V x):等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。

package chapter3.exchanger;

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

/**
 * @author czd
 */
public class ExchangerTest1 {
    public static void main(String[] args) {
        final Exchanger<String> exchanger = new Exchanger<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    String result = exchanger.exchange(" 我是来自Thread-A发送的数据!");
                    System.out.println(Thread.currentThread().getName() + " Result: " + result);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"Thread-A").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    TimeUnit.SECONDS.sleep(5);
                    String result = exchanger.exchange(" 我是来自Thread-B发送的数据!");
                    System.out.println(Thread.currentThread().getName() + " Result: " + result);
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        },"Thread-B").start();
    }
}

输出结果
在这里插入图片描述

②、exchange(V x, long timeout, TimeUnit unit):等待另一个线程到达此交换点(除非当前线程被中断,或者超出了指定的等待时间),然后将给定的对象传送给该线程,同时接收该线程的对象。

package chapter3.exchanger;

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

/**
 * @author czd
 */
public class ExchangerTest1 {
    public static void main(String[] args) {
        final Exchanger<String> exchanger = new Exchanger<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    String result = exchanger.exchange(" 我是来自Thread-A发送的数据!",3,TimeUnit.SECONDS);
                    System.out.println(Thread.currentThread().getName() + " Result: " + result);
                }catch (InterruptedException e){
                    e.printStackTrace();
                } catch (TimeoutException e){
                    System.out.println("超时了!");
                }

            }
        },"Thread-A").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    TimeUnit.SECONDS.sleep(5);
                    String result = exchanger.exchange(" 我是来自Thread-B发送的数据!");
                    System.out.println(Thread.currentThread().getName() + " Result: " + result);
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        },"Thread-B").start();
    }
}

输出结果
在这里插入图片描述

三、提出疑问–A:当使用Exchanger对两个线程进行数据交换时,线程A发送的东西,与线程B接收到的东西是否是一样的?(一样是指地址是否正确,而不仅仅是值一样)

下面是一个验证地址是否一样的代码案例

package chapter3.exchanger;

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

/**
 * @author czd
 */
public class ExchangerTest2 {
    public static void main(String[] args) {
        final Exchanger<Object> exchanger = new Exchanger<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    Object object = new Object();
                    Object obj = exchanger.exchange(object);
                    System.out.println(Thread.currentThread().getName() + " Thread-A send Object: " + object);
                    System.out.println(Thread.currentThread().getName() + " Thread-A get Object: " + obj);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }

            }
        },"Thread-A").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                try {
                    TimeUnit.SECONDS.sleep(5);
                    Object object = new Object();
                    Object obj = exchanger.exchange(object);
                    System.out.println(Thread.currentThread().getName() + " Thread-B send Object: " + object);
                    System.out.println(Thread.currentThread().getName() + " Thread-B get Object: " + obj);
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        },"Thread-B").start();
    }
}

输出结果
在这里插入图片描述
由图可以看出,线程A发送的东西与线程B接收到的东西是一样的,即连地址都是一样的

四、提出疑问–B:当使用Exchanger对两个线程进行数据交换时,是不是只能交换一次?能否多次的对两个线程进行数据的交换?

下面是一个验证是否能多次进行数据交换的代码案例

package chapter3.exchanger;

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

/**
 * @author czd
 */
public class ExchangerTest3 {
    public static void main(final String[] args) {
        final Exchanger<Integer> exchanger = new Exchanger<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                while (true){
                    try {
                        AtomicInteger atomicInteger = new AtomicInteger(1);
                        atomicInteger.set(exchanger.exchange(atomicInteger.get()));
                        System.out.println("Thread-A Value:" + atomicInteger.get());
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }


            }
        },"Thread-A").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始启动....");
                while (true){
                    try {
                        AtomicInteger atomicInteger = new AtomicInteger(2);
                        atomicInteger.set(exchanger.exchange(atomicInteger.get()));
                        System.out.println("Thread-B Value:" + atomicInteger.get());
                        TimeUnit.SECONDS.sleep(2);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }


            }
        },"Thread-B").start();
    }
}

输出结果
在这里插入图片描述
由图可以看出,使用Exchanger可以对两个线程进行多次的数据交换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值