Java高并发编程中Exchanger的使用及详细介绍-刘宇

本文详细介绍了Java高并发编程中Exchanger的作用与用法,包括其构造函数、exchange方法及其超时版本,通过实例演示了如何在成对线程间交换信息,并探讨了对象传递方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:刘宇
优快云博客地址:https://blog.youkuaiyun.com/liuyu973971883
有部分资料参考,如有侵权,请联系删除。如有不正确的地方,烦请指正,谢谢。

一、什么是Exchanger

主要用于一对线程之间交换信息,必须是给成对的线程使用。当线程A执行exchange方法时,则会等待线程B执行exchange方法,实现两个线程的想换转换信息。如果这两个线程之间有一个没有执行exchange方法,那么另一个将会被阻塞住,即两个线程必须都到达交换点。

二、Exchanger的基本使用

1、构造函数

  • 需要指定一个泛型,这里的泛型是指传递数据的类型。
Exchanger<V> exchanger = new Exchanger<V>();

2、exchange方法

  • x:需要传递的信息
  • 返回值:对方传递过来的信息
public V exchange(V x)

3、exchange方法

  • x:需要传递的信息
  • timeout:超时时间,如果在这时间内,另一个线程还未执行exchange,则抛出timeout异常
  • unit:时间单位
  • 返回值:对方传递过来的信息

注:当线程A出现了timeout时,则线程B在执行exchange时将会得不到回应,那线程B将会一直等待下去。

public V exchange(V x, long timeout, TimeUnit unit)

三、简单示例

1、exchange()

package com.brycen.concurrency03.exchanger;

import java.util.concurrent.Exchanger;

public class ExchangerExample1 {
	public static void main(String[] args) {
		final Exchanger<String> exchanger = new Exchanger<String>();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("Thread A start");
					String result = exchanger.exchange("I am from A");
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread A end");
			}
		},"==A==").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("Thread B start");
					String result = exchanger.exchange("I am from B");
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread B end");
			}
		},"==B==").start();
	}
}

输出结果:

  • 程序正常结束
Thread A start
Thread B start
==A== get result:[I am from B]
Thread A end
==B== get result:[I am from A]
Thread B end

2、exchange(V x, long timeout, TimeUnit unit)

package com.brycen.concurrency03.exchanger;

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

public class ExchangerExample1 {
	public static void main(String[] args) {
		final Exchanger<String> exchanger = new Exchanger<String>();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("Thread A start");
					//向线程B发送信息,超时时间为5秒
					String result = exchanger.exchange("I am from A",5,TimeUnit.SECONDS);
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (TimeoutException e) {
					e.printStackTrace();
					System.out.println("time out");
				}
				System.out.println("Thread A end");
			}
		},"==A==").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("Thread B start");
					//休眠10,让线程A出现超时异常
					TimeUnit.SECONDS.sleep(10);
					String result = exchanger.exchange("I am from B");
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread B end");
			}
		},"==B==").start();
	}
}

输出结果:

  • 程序无法结束,因为线程B还处于等待状态。
Thread A start
Thread B start
java.util.concurrent.TimeoutException
	at java.util.concurrent.Exchanger.exchange(Exchanger.java:626)
	at com.brycen.concurrency03.exchanger.ExchangerExample1$1.run(ExchangerExample1.java:15)
	at java.lang.Thread.run(Thread.java:745)
time out
Thread A end

3、exchange传递对象时,传递的是否是引用

package com.brycen.concurrency03.exchanger;

import java.util.concurrent.Exchanger;

public class ExchangerExample2 {
	public static void main(String[] args) {
		final Exchanger<Object> exchanger = new Exchanger<Object>();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Object aObj = new Object();
					System.out.println("A will send the object "+aObj);
					Object result = exchanger.exchange(aObj);
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread A end");
			}
		},"==A==").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Object bObj = new Object();
					System.out.println("B will send the object "+bObj);
					Object result = exchanger.exchange(bObj);
					System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread B end");
			}
		},"==B==").start();
	}
}

输出结果:

  • 从结果可以看出,exchange传递的对象是引用传递,即是同一个对象。那么值得注意的是,当这两个线程操作这个对象的时候就会出现线程安全问题。
A will send the object java.lang.Object@67437b8f
B will send the object java.lang.Object@28c5e3c5
==B== get result:[java.lang.Object@67437b8f]
Thread B end
==A== get result:[java.lang.Object@28c5e3c5]
Thread A end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值