高并发编程之Exchanger工具类讲解
2019-02-22 19:58
134 查看
一、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() { 20000 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可以对两个线程进行多次的数据交换
相关文章推荐
- 高并发编程之ReentrantLock工具类讲解
- 高并发编程之ReentrantReadWriteLock工具类讲解
- 高并发编程之Condition工具类讲解
- JAVA 并发编程随笔【四】Collections集合工具类(学习并发编程顺带学习)
- JAVA 并发编程随笔【四】Collections集合工具类(学习并发编程顺带学习)
- Exchanger 并发工具类
- Exchanger 并发工具类
- 高并发编程之ArrayBlockingQueue讲解
- 高并发编程之ConcurrentLinkedQueue讲解
- JAVA 并发编程随笔【四】Collections集合工具类(学习并发编程顺带学习)
- 【Java并发编程实战】-----“J.U.C”:Exchanger
- 高并发编程之PriorityBlockingQueue讲解
- 高并发编程之ConcurrentLinkedDeque讲解
- 多线程进阶之并发工具类第二篇:Semaphore、Exchanger
- JAVA 并发编程随笔【四】Collections集合工具类(学习并发编程顺带学习)
- Java并发编程-同步辅助类之Exchanger
- java并发编程2.3并发工具类——Semaphore、Exchange、FutureTask
- Java并发编程之——同步器工具类(semaphores, barriers, CountDownLatch,exchangers)
- 并发工具类CountDownLatch、CyclicBarrier、Semaphore、Exchanger详解
- 第8章 Java中的并发工具类(CountDownLatch CyclicBarrier Semaphore Exchanger)