簡(jiǎn)介
Exchanger(交換者),一個(gè)用于線程間協(xié)作的工具類。Exchanger用于線程間的數(shù)據(jù)交換,提供了一個(gè)同步點(diǎn),兩個(gè)線程可以在這個(gè)同步點(diǎn)交換彼此的數(shù)據(jù)。
構(gòu)造方法
Exchanger()
所有方法
exchange(V x)
等待另一個(gè)線程到達(dá)這個(gè)交換點(diǎn)(除非當(dāng)前線程interrupted),然后與另一線程交換數(shù)據(jù)對(duì)象。
exchange(V x, long timeout, TimeUnit unit)
等待另一個(gè)線程到達(dá)這個(gè)交換點(diǎn)(除非當(dāng)前線程interrupted或超過(guò)指定的等待時(shí)間),然后與另一線程交換數(shù)據(jù)對(duì)象。
簡(jiǎn)單示例
有個(gè)羊集,就是各家農(nóng)戶都拉著自家的羊來(lái)賣,或者來(lái)買幾只合適的羊。賣羊的和買羊的就可以看做是兩個(gè)線程,買羊的手里拿著錢,賣羊的手里牽著羊,這筆買賣交易成功后,買羊的手里就牽著羊,賣羊的手里就拿著錢了。
import java.util.concurrent.Exchanger;
/**
* Created by bxw on 2017/12/3.
*/
public class SheepMarket {
Exchanger<String> exchanger = new Exchanger<>();
public static void main(String[] args) {
SheepMarket sheepMarket = new SheepMarket();
System.out.println("**************開(kāi)市了*************");
SheepMarket.BuySheep buySheep = sheepMarket.new BuySheep();
SheepMarket.SaleSheep saleSheep = sheepMarket.new SaleSheep();
Thread thread1 = new Thread(buySheep);
Thread thread2 = new Thread(saleSheep);
thread1.start();
thread2.start();
}
public class BuySheep implements Runnable{
String person = "買羊的說(shuō): ";
String money = "我有1000塊錢";
@Override
public void run() {
System.out.println(person + "我要買羊," + money);
try {
String sheep = exchanger.exchange(money);
System.out.println(person + "羊買完了," + sheep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class SaleSheep implements Runnable{
String person = "賣羊的說(shuō): ";
String sheep = "我手里牽著羊";
@Override
public void run() {
System.out.println(person + "我要賣羊," + sheep);
try {
String money = exchanger.exchange(sheep);
System.out.println(person + "羊賣完了," + money);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

上面的這個(gè)例子使用了exchange(V x)方法,下面再來(lái)看看exchange
(V x, long timeout, TimeUnit unit)這個(gè)方法,買羊的要買羊,賣羊的如果長(zhǎng)時(shí)間不理買羊的,買羊的就走了。
將BuySheep和SaleSheep稍作修改:
public class SheepMarket {
Exchanger<String> exchanger = new Exchanger<>();
public static void main(String[] args) {
SheepMarket sheepMarket = new SheepMarket();
System.out.println("**************開(kāi)市了*************");
SheepMarket.BuySheep buySheep = sheepMarket.new BuySheep();
SheepMarket.SaleSheep saleSheep = sheepMarket.new SaleSheep();
Thread thread1 = new Thread(buySheep);
Thread thread2 = new Thread(saleSheep);
thread1.start();
thread2.start();
}
public class BuySheep implements Runnable{
String person = "買羊的說(shuō): ";
String money = "我有1000塊錢";
@Override
public void run() {
System.out.println(person + "我要買羊," + money);
try {
String sheep = exchanger.exchange(money, 8000, TimeUnit.MILLISECONDS);
System.out.println(person + "羊買完了," + sheep);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
System.err.println("麻蛋,不理我,老子還不買了");
}
}
}
public class SaleSheep implements Runnable{
String person = "賣羊的說(shuō): ";
String sheep = "我手里牽著羊";
@Override
public void run() {
System.out.println(person + "我要賣羊," + sheep);
try {
Thread.sleep(9000);
String money = exchanger.exchange(sheep);
System.out.println(person + "羊賣完了," + money);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

把SaleSheep中Thread.sleep(9000)的睡眠時(shí)間縮短至8000以下依舊可以成功交換數(shù)據(jù)對(duì)象。
總結(jié)
如果兩個(gè)線程有一個(gè)沒(méi)有執(zhí)行exchange(V x)方法,就會(huì)一直等待,如果擔(dān)心有特殊情況發(fā)生,避免一直傻等,可以使用exchange(V x, long timeout, TimeUnit unit)。Exchanger還可用于校對(duì)工作,比如要對(duì)一批數(shù)據(jù)進(jìn)行錄入到excel,為了避免錯(cuò)誤,可有甲乙二人進(jìn)行錄入,然后由系統(tǒng)加載這兩個(gè)Excel,并比較是否錄入一致。