Exchanger的使用
来源:互联网 发布:java漏洞检测工具 编辑:程序博客网 时间:2024/06/04 18:33
类Exchanger的功能可以使2个线程之间传输数据,它比生产者/消费者模式使用的wait/notify要更加方便。所以本次将介绍此类在2个线程之间传递任意数据类型的数据,Exchanger类的使用与结构相当简单,主要的学习点就是exchange()方法。
方法exchange()阻塞的特性
类Exchanger中的exchange()方法具有阻塞的特色,也就是次方法被调用后等待其他线程来取数据,如果没有其他线程取得数据,则一直阻塞。
创建测试用的项目Exchanger_1,创建类ThreadA.java代码如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ThreadA extends Thread{Exchanger<String> exchanger = new Exchanger<String>();public ThreadA(Exchanger<String> exchanger){this.exchanger = exchanger;}@Overridepublic void run() {super.run();try {System.out.println("在线程A中得到线程B的值=" + exchanger.exchange("中国人A"));System.out.println("A end!");} catch (InterruptedException e) {e.printStackTrace();}}}运行时类ExchangerTest.java代码如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ExchangerTest {public static void main(String[] args) {Exchanger<String> exchanger = new Exchanger<String>();ThreadA a = new ThreadA(exchanger);a.start();System.out.println("main end!");}}运行结果如下:
方法exchange()传递数据
创建测试用的项目Exchanger_2,创建ThreadA.java类代码如下:package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ThreadA extends Thread{Exchanger<String> exchanger = new Exchanger<String>();public ThreadA(Exchanger<String> exchanger){this.exchanger = exchanger;}@Overridepublic void run() {super.run();try {System.out.println("在线程A中得到线程B的值=" + exchanger.exchange("中国人A"));} catch (InterruptedException e) {e.printStackTrace();}}}创建类ThreadB.java代码如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ThreadB extends Thread{Exchanger<String> exchanger = new Exchanger<String>();public ThreadB(Exchanger<String> exchanger){this.exchanger = exchanger;}@Overridepublic void run() {super.run();try {System.out.println("在线程B中得到线程A的值=" + exchanger.exchange("中国人B"));} catch (InterruptedException e) {e.printStackTrace();}}}运行类ExchangerTest.java如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ExchangerTest {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();}}运行结果为:
方法exchange(V x, long timeout, TimeUnit unit)与超时
当调用exchange(V x, long timeout, TimeUnit unit)方法后在指定的时间内没有其他线程获取数据,则出现超时异常。创建测试用的项目Exchanger_3,创建类ThreadA.java代码如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;import java.util.concurrent.TimeUnit;import java.util.concurrent.TimeoutException;public class ThreadA extends Thread{Exchanger<String> exchanger = new Exchanger<String>();public ThreadA(Exchanger<String> exchanger){this.exchanger = exchanger;}@Overridepublic void run() {super.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();}}}
运行类ExchangerTest.java代码如下:
package com.yc.exchanger;import java.util.concurrent.Exchanger;public class ExchangerTest {public static void main(String[] args) {Exchanger<String> exchanger = new Exchanger<String>();ThreadA a = new ThreadA(exchanger);a.start();System.out.println("main end!");}}
测试结果为:
下面看一下exchange()方法的源码:
/** * Waits for another thread to arrive at this exchange point (unless * the current thread is {@linkplain Thread#interrupt interrupted}), * and then transfers the given object to it, receiving its object * in return.(在当前线程不被打断的情况下等待其他线程到达exchange点,然后转换其他线程带来的Object) * * <p>If another thread is already waiting at the exchange point then * it is resumed for thread scheduling purposes and receives the object * passed in by the current thread. The current thread returns immediately, * receiving the object passed to the exchange by that other thread. * * <p>If no other thread is already waiting at the exchange then the * current thread is disabled for thread scheduling purposes and lies * dormant until one of two things happens: * <ul> * <li>Some other thread enters the exchange; or * <li>Some other thread {@linkplain Thread#interrupt interrupts} * the current thread. * </ul> * <p>If the current thread: * <ul> * <li>has its interrupted status set on entry to this method; or * <li>is {@linkplain Thread#interrupt interrupted} while waiting * for the exchange, * </ul> * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. * * @param x the object to exchange(参数x指的是要去交换的对象) * @return the object provided by the other thread(返回的是其他线程提供的对象) * @throws InterruptedException if the current thread was * interrupted while waiting(当当前正在等待的线程被打断时抛出InterruptedException异常) */ public V exchange(V x) throws InterruptedException { if (!Thread.interrupted()) { //如果当前线程未中断 Object v = doExchange((x == null) ? NULL_ITEM : x, false, 0); if (v == NULL_ITEM) return null;//NULL_ITEM 和 CANCEL都是Exchanger类的两个私有的、静态的、不可变的对象,且都new了 //private static final Object CANCEL = new Object(); //private static final Object NULL_ITEM = new Object(); if (v != CANCEL) return (V)v; Thread.interrupted(); // Clear interrupt status on IE throw } throw new InterruptedException(); }
private Object doExchange(Object item, boolean timed, long nanos) { Node me = new Node(item); // Create in case occupying(Node是Exchanger类的一个内部类有两个 //变量 public final Object item; 和 public volatile Thread waiter;) int index = hashIndex(); // Index of current slot int fails = 0; // Number of CAS failures for (;;) { Object y; // Contents of current slot Slot slot = arena[index]; if (slot == null) // Lazily initialize slots createSlot(index); // Continue loop to reread else if ((y = slot.get()) != null && // Try to fulfill slot.compareAndSet(y, null)) { Node you = (Node)y; // Transfer item if (you.compareAndSet(null, item)) { LockSupport.unpark(you.waiter); return you.item; } // Else cancelled; continue } else if (y == null && // Try to occupy slot.compareAndSet(null, me)) { if (index == 0) // Blocking wait for slot 0 return timed ? awaitNanos(me, slot, nanos) : await(me, slot); Object v = spinWait(me, slot); // Spin wait for non-0 if (v != CANCEL) return v; me = new Node(item); // Throw away cancelled node int m = max.get(); if (m > (index >>>= 1)) // Decrease index max.compareAndSet(m, m - 1); // Maybe shrink table } else if (++fails > 1) { // Allow 2 fails on 1st slot int m = max.get(); if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1)) index = m + 1; // Grow on 3rd failed slot else if (--index < 0) index = m; // Circularly traverse } } }
有兴趣的同学完全可以去研究研究Exchanger这个类。
0 0
- Exchanger的使用
- Exchanger的使用
- 交换函数Exchanger的使用
- 【Java并发编程】02.Exchanger的使用
- java再复习-Exchanger的使用
- Exchanger工具类的使用案例
- 16-Exchanger使用
- 【java并发】线程同步工具Exchanger的使用
- java并发编程系列之Exchanger的使用
- Java并发编程核心方法与框架-exchanger的使用
- Java并发编程——Exchanger的使用
- Exchanger的简单示例
- Exchanger的基本用法
- Exchanger
- Exchanger
- Exchanger
- Exchanger
- Exchanger
- java语法整理
- HEXO deployer 问题
- 高等数学-对无穷小无穷大的理解
- kNN与kMeans聚类算法的区别
- 欢迎使用CSDN-markdown编辑器
- Exchanger的使用
- 随性
- 数据结构-高级排序
- 【NDN安全】Poseidon: Mitigating Interest Flooding DDoS Attacks in Named Data Networking 学习笔记
- jQuery插件slides实现无缝轮播图特效
- C++_CopyConstructor(副本构造器 防止指针重复释放)
- 非计算机专业,如何学习计算机视觉?
- 寻找丑数
- 九度OJ-题目1173:查找-10网研上机A