本例介紹第四個同步裝置:Exchanger,它讓兩個線程呼喚信息。本實例模擬服務生和顧客,服務生往空杯子中倒水,顧客從裝滿水的杯子中喝水,然后互換杯子,服務生接著倒水,顧客接著喝水。
初始化Exchanger對象時,可以通過泛型指定杯子能交換的信息類型。如“new Exchanger<String>;” 表示只能交換String類型的信息。
Exchanger的exchanger方法表示當前線程準備交換信息,等待其他線程與它交換信息。當有其他線程調用該Exchanger對象的exchange方法時,立即交換信息。

import java.util.concurrent.Exchanger;

/**
* Exchanger讓兩個線程可以互換信息。
* 例子中服務生線程往空的杯子里倒水,顧客線程從裝滿水的杯子里喝水,
* 然后通過Exchanger雙方互換杯子,服務生接著往空杯子里倒水,顧客接著喝水,
* 然后交換,如此周而復始。
*/
public class ExchangerTest {

// 描述一個裝水的杯子
public static class Cup{
// 標識杯子是否有水
private boolean full = false;
public Cup(boolean full){
this.full = full;
}
// 添水,假設需要5s
public void addWater(){
if (!this.full){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
this.full = true;
}
}
// 喝水,假設需要10s
public void drinkWater(){
if (this.full){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
this.full = false;
}
}
}
public static void testExchanger() {
// 初始化一個Exchanger,并規定可交換的信息類型是杯子
final Exchanger<Cup> exchanger = new Exchanger<Cup>();
// 初始化一個空的杯子和裝滿水的杯子
final Cup initialEmptyCup = new Cup(false);
final Cup initialFullCup = new Cup(true);

//服務生線程
class Waiter implements Runnable {
public void run() {
Cup currentCup = initialEmptyCup;
try {
int i=0;
while (i < 2){
System.out.println("服務生開始往杯子中添水:"
+ System.currentTimeMillis());
// 往空的杯子里加水
currentCup.addWater();
System.out.println("服務生添水完畢:"
+ System.currentTimeMillis());
// 杯子滿后和顧客的空杯子交換
System.out.println("服務生等待與顧客交換杯子:"
+ System.currentTimeMillis());
currentCup = exchanger.exchange(currentCup);
System.out.println("服務生與顧客交換杯子完畢:"
+ System.currentTimeMillis());
i++;
}

} catch (InterruptedException ex) {
}
}
}

//顧客線程
class Customer implements Runnable {
public void run() {
Cup currentCup = initialFullCup;
try {
int i=0;
while (i < 2){
System.out.println("顧客開始喝水:"
+ System.currentTimeMillis());
//把杯子里的水喝掉
currentCup.drinkWater();
System.out.println("顧客喝水完畢:"
+ System.currentTimeMillis());
//將空杯子和服務生的滿杯子交換
System.out.println("顧客等待與服務生交換杯子:"
+ System.currentTimeMillis());
currentCup = exchanger.exchange(currentCup);
System.out.println("顧客與服務生交換杯子完畢:"
+ System.currentTimeMillis());
i++;
}
} catch (InterruptedException ex) {
}
}
}
new Thread(new Waiter()).start();
new Thread(new Customer()).start();
}
public static void main(String[] args) {
ExchangerTest.testExchanger();
}
}
















































































































-- 學海無涯