Exchanger的使用

简介

Exchanger类的功能是可以使2两个线程之间传输数据,它比生产者、消费者模式使用的wait/notify要更加方便

API介绍

exchange()及其重载方法的使用
1.1、阻塞性
Exchanger类中的exchange()方法具有阻塞的特色,也就是此方法在被调用后等待其他线程来获取数据,如果没有其他线程取得数据,在一直阻塞等待。

案例如下:

public class ThreadA extends Thread {

	private Exchanger<String> exchanger;
	
	public ThreadA(Exchanger<String> exchanger) {
		super();
		this.exchanger = exchanger;
	}
	
	@Override
	public void run() {
		try {
			System.out.println("在线程A中得到线程B的值="+exchanger.exchange("中国人A"));
			System.out.println("A end!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {

	public static void main(String[] args) {
		Exchanger<String> exchanger = new Exchanger<String>();
		ThreadA a = new ThreadA(exchanger);
		a.start();
		System.out.println("main end!");
	}
}

运行结果如下:
在这里插入图片描述
可以看到线程A处于阻塞状态

1.2、传递数据
等待另一个线程到达此交换点(除非当前线程为interrupted ),然后将给定对象传输给它,接收其对象作为回报。
如果另一个线程已经在交换点处等待,那么它将恢复为线程调度目的,并接收当前线程传入的对象。 当前线程立即返回,接收通过该另一线程传递到交换机的对象。
如果没有其他线程已经在交换机上等待,那么当前线程被禁用以进行线程调度,并且休眠,直到发生两件事情之一:
一些其他线程进入交换机; 要么
一些其他线程interrupts当前线程。
如果当前线程:在进入该方法时设置了中断状态; 要么是等待交换interrupted ,然后InterruptedException被关上,当前线程的中断状态被清除。

案例如下:

public class ThreadB extends Thread {

	private Exchanger<String> exchanger;
	
	public ThreadB(Exchanger<String> exchanger) {
		super();
		this.exchanger = exchanger;
	}
	
	@Override
	public void run() {
		try {
			System.out.println("在线程B中得到线程A的值="+exchanger.exchange("中国人B"));
			System.out.println("B end!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {

	public static void main(String[] args) {
		Exchanger<String> exchanger = new Exchanger<String>();
		ThreadA a = new ThreadA(exchanger);
		
		ThreadB b = new ThreadB(exchanger);
		a.start();
		b.start();
	}
}

运行结果如下:
在这里插入图片描述
此时线程A和线程B交换了数据

1.3、超时处理
当调用exchange(V x, long timeout, TimeUnit unit)方法后在指定的时间内没有其他线程获取数据,则抛出超时异常

案例如下:

public class ThreadA extends Thread {

	private Exchanger<String> exchanger;
	
	public ThreadA(Exchanger<String> exchanger) {
		super();
		this.exchanger = exchanger;
	}
	
	@Override
	public void run() {
		try {
			System.out.println("在线程A中得到线程B的值="+exchanger.exchange("中国人A",5,TimeUnit.SECONDS));
			System.out.println("A end!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (TimeoutException e) {
			e.printStackTrace();
		}
	}
}
public class Run {

	public static void main(String[] args) {
		Exchanger<String> exchanger = new Exchanger<String>();
		ThreadA a = new ThreadA(exchanger);
		a.start();
		System.out.println("main end!");
	}
}

结果如下:
在这里插入图片描述
当等到5秒之后没有其他线程进行数据交互,抛出超时异常。

exchanger的API主要使用exchange方法,所以本篇文章只对此方法进行梳理。

现在将Semaphore和Exchanger类做如下总结:
Semaphore类的主要作用是限制并发执行的线程个数,它具有synchronized所不具有的强大功能,比如等待获取许可的同时可以加入等待时间,还有尝试是否可以持有锁等扩展功能,可以说Semaphore类是强有力的控制并发线程个数的解决方案之一,而Exchanger类是线程间传输数据的方式之一,而且在传输的数据类型上没有任何限制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

升仔聊编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值