并发技术_2_Exchanger

本文详细介绍了Java并发工具类Exchanger的使用方法,包括基本概念、线程间的同步数据交换、阻塞特性及超时处理等内容。

Exchanger

 

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

 

Exchanger(交换者)是一个用于线程间协作的工具类。它用于线程间的数据交换。

如果第一个线程先执行了exchanger方法,它会一直等待第二个线程也执行exchanger,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程产生的数据传递给对象。

 


第一个Demo

public class ExhcangerTest {

	private static final Exchanger<String> exgr = new Exchanger<String>();

	// 创建固定大小的线程池
	private static ExecutorService threadPool = Executors.newFixedThreadPool(2);

	public static void main(String[] args) {

	threadPool.execute(new Runnable() {

	@Override
	public void run() {
			try {
					String A = "银行流水A";
					System.out.println("A先睡一会");
					TimeUnit.SECONDS.sleep(5);
					System.out.println("A : " + exgr.exchange(A));
			} catch (Exception e) {
					e.printStackTrace();
			}
	}
	});

	threadPool.execute(new Runnable() {

	@Override
	public void run() {
			try {
					String B = "银行流水B";
					System.out.println("B准备好了");
					System.out.println("B : " + exgr.exchange(B));
			} catch (Exception e) {
					e.printStackTrace();
			}
	}
	});

	threadPool.shutdown();

	}

}

输出结果:
	A先睡一会
	B准备好了
	A : 银行流水B
	B : 银行流水A
	

这个Demo可以看出,如果两个线程有一个线程没有到达exchange方法,则会一直等待下去,如果担心有特殊情况,想避免一直等待,

可以使用exchange(V x , long timeout , TimeUnit unit)设置最长等待时间。

 


 

方法exchange()阻塞的特性

Exchanger中的exchange()方法具有阻塞的特点,也就是此方法被调用后等待其他线程来读取数据,如果没有线程来读取数据,则一直阻塞下去。

 

我们通过一个Demo,来看下线程阻塞效果:

public class ThreadA extends Thread {

	private Exchanger<String> exchanger;

	public ThreadA(Exchanger<String> exchanger) {
			this.exchanger = exchanger;
	}

	@Override
	public void run() {

	try {

	System.out.println("在线程A中得到线程B的值 = " + exchanger.exchange("中国人A"));
	System.out.println("A end");

	} catch (Exception 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");

	}

}

输出结果:


可以看出,虽然main运行完毕,但ThreadA一直在线程阻塞中。



 

方法exchange()传递数据

ThreadA ThreadB 之间互相传递数据

public class ThreadA extends Thread {

	private Exchanger<String> exchanger;

	public ThreadA(Exchanger<String> exchanger) {
			this.exchanger = exchanger;
	}

	@Override
	public void run() {

	try {

	System.out.println("线程A得到线程B的值 = " + exchanger.exchange("中国人A"));

	} catch (Exception e) {
			e.printStackTrace();
	}

	}

}

public class ThreadB extends Thread {

	private Exchanger<String> exchanger;

	public ThreadB(Exchanger<String> exchanger) {
			this.exchanger = exchanger;
	}

	@Override
	public void run() {

	try {

	System.out.println("线程B得到线程A的值 = " + exchanger.exchange("中国人B"));

	} catch (Exception 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互相传递了数据。

(看的有些云里雾里,后面找资料补全)

 

 


方法exchange(Vx,long timeout,TimeUnit unit)与超时

当调用exchange(V x,longtimeout,TimeUnit unit)方法后,在指定的时间内没有其他线程获取数据,则会出现超时异常。

public class ThreadA extends Thread {

	private Exchanger<String> exchanger;

	public ThreadA(Exchanger<String> exchanger) {
			this.exchanger = exchanger;
	}

	@Override
	public void run() {

	try {

	System.out.println("在线程A中得到线程B的值 = " + exchanger.exchange("中国人A", 5, TimeUnit.SECONDS));

	} catch (Exception 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秒之后,因为没有其他线程调用,抛出超时异常。


小结:

 

Semaphore的主要作用是限制并发执行的线程数量,它具有synchronized所不具备的强大功能,比如:

  1. 等待获取许可的同时加入等待时间
  2. 尝试是否可以持有锁这些扩展功能

 

Exchanger是线程间传输数据的方式之一,而且在传输的数据类型上并没有任何限制。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值