1. 程式人生 > >Java多執行緒/併發25、Exchanger執行緒資料交換

Java多執行緒/併發25、Exchanger執行緒資料交換

Exchanger用於執行緒間的資料交換。它提供一個同步點,在這個同步點兩個執行緒可以交換彼此的資料。
這句話說到兩個關鍵點:

  • Exchanger只能用於兩個執行緒互相交換資料。如果有三個執行緒呢?對不起,臣妾做不到……
  • Exchanger會產生一個同步點。一個執行緒先執行到達同步點,就會阻塞,等到另一個執行緒。兩個都到達同步點後,開始交換資料。執行緒方法中呼叫exchanger.exchange()的地方就是同步點。

來看例子:
在學校讀書時做算術題,通常先用正常思維計算結果,然後換一種方式驗算,兩個結果一致就說明做對了。以前還見過打算盤打得好的人,可以用兩隻手打,一隻手計算,一隻手驗算。典型的多執行緒……我也想學這門手藝,於是那位先生要我先試試左手寫1,2,3,4,5,右手寫5,4,3,2,1,然後我就沒學了。。。。。。
下面的程式通過兩個執行緒計算50*70的值,各自計算完後,通過exchanger交換結果,如果一致就算成功。

public class ExchangerDemo {
    public static void main(String[] args) {
        final Exchanger<Integer> exgr = new Exchanger<Integer>();
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        /*執行緒1用於計算結果*/
        threadPool.execute(new Runnable() {
            @Override
            public
void run() { int result=50*70; try { System.out.println("執行緒"+Thread.currentThread().getName()+"計算50*70的結果是:"+result); /*同步點。先到達的執行緒會在這裡等侯*/ exgr.exchange(result); } catch (InterruptedException e) { e.printStackTrace(); } } }); /*執行緒2用於計算並檢驗*/
threadPool.execute(new Runnable() { @Override public void run() { int result=0; for(int i=0;i<50;i++){ result+=70; } System.out.println("執行緒"+Thread.currentThread().getName()+"計算50*70的結果是:"+result); try { /*同步點。先到達的執行緒會在這裡等侯*/ int result_FromOtherThread=exgr.exchange(result); System.out.println("執行緒"+Thread.currentThread().getName()+"從另一個執行緒獲取得值是:"+result_FromOtherThread); if(result_FromOtherThread==result){ System.out.println("兩邊計算結果一樣,驗證成功"); }else{ System.out.println("兩邊計算結果不一樣,驗證失敗"); } } catch (InterruptedException e) { e.printStackTrace(); } } }); } }

輸出:

執行緒pool-1-thread-1計算50*70的結果是:3500
執行緒pool-1-thread-2計算50*70的結果是:3500
執行緒pool-1-thread-2從另一個執行緒獲取得值是:3500
兩邊計算結果一樣,驗證成功

可以把執行緒1的int result=50*70;改一下,看看輸出什麼。

如果兩個執行緒有一個因為中斷或崩潰沒有到達exchange方法,另一個則會一直等待。如果擔心有特殊情況發生,避免一直等待,可以使用exchange(V x, long timeout, TimeUnit unit)設定最大等待時長。

如上面例子中的第二個執行緒,只等待5秒:

exgr.exchange(result,5,TimeUnit.SECONDS);