簡介
Exchanger(交換者),一個用于線程間協(xié)作的工具類。Exchanger用于線程間的數(shù)據(jù)交換,提供了一個同步點晴裹,兩個線程可以在這個同步點交換彼此的數(shù)據(jù)。
構(gòu)造方法
Exchanger()
所有方法
exchange(V x)
等待另一個線程到達這個交換點(除非當前線程interrupted)救赐,然后與另一線程交換數(shù)據(jù)對象涧团。
exchange(V x, long timeout, TimeUnit unit)
等待另一個線程到達這個交換點(除非當前線程interrupted或超過指定的等待時間),然后與另一線程交換數(shù)據(jù)對象。
簡單示例
有個羊集泌绣,就是各家農(nóng)戶都拉著自家的羊來賣钮追,或者來買幾只合適的羊。賣羊的和買羊的就可以看做是兩個線程阿迈,買羊的手里拿著錢元媚,賣羊的手里牽著羊,這筆買賣交易成功后仿滔,買羊的手里就牽著羊惠毁,賣羊的手里就拿著錢了。
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("**************開市了*************");
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 = "買羊的說: ";
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 = "賣羊的說: ";
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();
}
}
}
}
上面的這個例子使用了exchange(V x)方法飒焦,下面再來看看exchange
(V x, long timeout, TimeUnit unit)這個方法蜈膨,買羊的要買羊,賣羊的如果長時間不理買羊的牺荠,買羊的就走了翁巍。
將BuySheep和SaleSheep稍作修改:
public class SheepMarket {
Exchanger<String> exchanger = new Exchanger<>();
public static void main(String[] args) {
SheepMarket sheepMarket = new SheepMarket();
System.out.println("**************開市了*************");
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 = "買羊的說: ";
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 = "賣羊的說: ";
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)的睡眠時間縮短至8000以下依舊可以成功交換數(shù)據(jù)對象驰凛。
總結(jié)
如果兩個線程有一個沒有執(zhí)行exchange(V x)方法,就會一直等待担扑,如果擔心有特殊情況發(fā)生恰响,避免一直傻等,可以使用exchange(V x, long timeout, TimeUnit unit)涌献。Exchanger還可用于校對工作胚宦,比如要對一批數(shù)據(jù)進行錄入到excel,為了避免錯誤燕垃,可有甲乙二人進行錄入枢劝,然后由系統(tǒng)加載這兩個Excel,并比較是否錄入一致卜壕。