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类是线程间传输数据的方式之一,而且在传输的数据类型上没有任何限制。

你可能感兴趣的:(JUC学习笔记,Java)