类Exchanger的功能可以使2个线程之间传输数据,它比生产者/消费者模式使用的wait/notify要更加方便。所以本次将介绍此类在2个线程之间传递任意数据类型的数据,Exchanger类的使用与结构相当简单,主要的学习点就是exchange()方法。
package com.yc.exchanger;
import java.util.concurrent.Exchanger;
public class ThreadA extends Thread{
Exchanger exchanger = new Exchanger();
public ThreadA(Exchanger exchanger){
this.exchanger = exchanger;
}
@Override
public 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 exchanger = new Exchanger();
ThreadA a = new ThreadA(exchanger);
a.start();
System.out.println("main end!");
}
}
运行结果如下:
package com.yc.exchanger;
import java.util.concurrent.Exchanger;
public class ThreadA extends Thread{
Exchanger exchanger = new Exchanger();
public ThreadA(Exchanger exchanger){
this.exchanger = exchanger;
}
@Override
public 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 exchanger = new Exchanger();
public ThreadB(Exchanger exchanger){
this.exchanger = exchanger;
}
@Override
public 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 exchanger = new Exchanger();
ThreadA a = new ThreadA(exchanger);
ThreadB b = new ThreadB(exchanger);
a.start();
b.start();
}
}
运行结果为:
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 exchanger = new Exchanger();
public ThreadA(Exchanger exchanger){
this.exchanger = exchanger;
}
@Override
public 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();
}
}
}
package com.yc.exchanger;
import java.util.concurrent.Exchanger;
public class ExchangerTest {
public static void main(String[] args) {
Exchanger exchanger = new Exchanger();
ThreadA a = new ThreadA(exchanger);
a.start();
System.out.println("main end!");
}
}
/**
* 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)
*
* 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.
*
*
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:
*
* - Some other thread enters the exchange; or
*
- Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
*
* If the current thread:
*
* - has its interrupted status set on entry to this method; or
*
- is {@linkplain Thread#interrupt interrupted} while waiting
* for the exchange,
*
* 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
}
}
}