1. 程式人生 > >Java執行緒--Exchanger交換器

Java執行緒--Exchanger交換器

Exchanger<T>交換器

目錄

Exchanger交換器

Exchanger概念 

Exchanger示例 

Exchanger和Semaphore區別 

 借花獻佛


Exchanger<T>概念 

Exchanger

上圖業務場景描述:A有球,想要和B的魚互動,整個互動過程描述如下:

A在準備素材,球,準備的比較快,然後就發出交換訴求,exchange(球),發現B還沒帶著魚來,就阻塞在這裡。B這時還在釣魚,等B釣到魚後,立馬發出交換訴求,exchange(魚),發現A阻塞在那裡了,就把A喚醒,然後兩人互換了東西,A擁有了魚,B擁有了球。

 

A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return. An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.

    在以上的描述中,有幾個要點:

  • 交換值是同步的
  • 成對的執行緒之間交換資料;
  • 可看成是雙向的同步佇列;
  • 可應用於演演算法、流水線設計;

Exchanger<V>類中的主要方法就是:exchange(V x)方法,成對的兩個執行緒之間,都呼叫了該方法,就能在兩個執行緒彼此都準備好資料後,成功的交換資料給對方,然後各自返回。如果想支援成對的兩個執行緒之間,一個沒耐性,等的時間過長,或者被打斷了就不交換資料了,可以使用exchange(V x, long timeout, TimeUnit unit)方法。


Exchanger<T>示例 

import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;

//球執行緒
class BallTask implements Runnable
{
    private Exchanger<String> e;
    public BallTask(Exchanger<String> e){
	this.e = e;
    }

    public void run(){
	try{
	    long sleepTime = (long)(Math.random() * 2500) ;
	    String tName = Thread.currentThread().getName();
	    System.out.println(tName+"正在買球,用時["+sleepTime+"]才買到球,趕緊去換魚...");
	    Thread.sleep(sleepTime);
	    String str = e.exchange(tName+":的球");
	    System.out.println("【"+tName+":的球】換到了-->【"+str+"】");
	}
	catch(Exception e){
	}
	finally{
	}
    }
}


//魚執行緒
class FishTask implements Runnable
{
    private Exchanger<String> e;
    public FishTask(Exchanger<String> e){
	this.e = e;
    }

    public void run(){
	try{
	    long sleepTime = (long)(Math.random() * 2500) ;
            String tName = Thread.currentThread().getName();
	    System.out.println(tName+"正在釣魚,用時["+sleepTime+"]才釣到魚,趕緊去換球...");
	    Thread.sleep(sleepTime);
	    String str = e.exchange(tName+":的魚");
	    System.out.println("【"+tName+":的魚】換到了-->【"+str+"】");
	}
	catch(Exception e){
	}
	finally{
	}
    }
}

public class ExchangerTest
{
    public static void main(String[] args) 
    {
	Exchanger<String> e = new Exchanger<String>();

	BallTask bTask = new BallTask(e);		//任務:球執行緒
	FishTask fTask = new FishTask(e);		//任務:魚執行緒

	Thread bThread = new Thread(bTask,"Ball");
	Thread fThread = new Thread(fTask,"Fish");

	bThread.start();
	fThread.start();

	System.out.println("我是主執行緒,準備看看你們交易情況...\n\r");

	try{
	    bThread.join();
	    fThread.join();
	}catch(Exception ep){}

	System.out.println("\n\r我是主執行緒,已看到你們的交易結果...");
    }
}

程式執行結果如下:

我是主執行緒,準備看看你們交易情況...

Ball正在買球,用時[88]才買到球,趕緊去換魚...
Fish正在釣魚,用時[2215]才釣到魚,趕緊去換球...

【Fish:的魚】換到了-->【Ball:的球】
【Ball:的球】 換到了-->【Fish:的魚】

我是主執行緒,已看到你們的交易結果...


Exchanger和Semaphore區別 

Exchanger<V>交換器和Semaphore訊號量在關於生產者消費者《產1消1模式》運用的區別:

  • Exchanger交換器:成對的兩個執行緒,各個執行緒有各個執行緒的自己資料V,A執行緒擁有V1,B執行緒擁有V2,V1<...>V2互換。 
  • Semaphore訊號量:成對的兩個執行緒,只需一個數據池即可,生產者生產資料注入資料池,消費者從資料池取走資料消費。
  • Exchanger交換器:兩個執行緒之間的通訊僅僅一個Exchanger例項即可。
  • Semaphore訊號量:兩個執行緒之間的通訊需要兩個訊號量,生產訊號指示燈,消費訊號指示燈。
  • Exchanger和Semaphore的共同點:兩個執行緒之間需要同步通訊。生產的過快,沒用,必須等消費完了,才能進行下一生產1;同理,消費的過快,也沒用,必須等生產完了,才能進行下一消費1。

 借花獻佛

摘自部落格(http://brokendreams.iteye.com/blog/2253956)

其實就是”我”和”你”(可能有多個”我”,多個”你”)在一個叫Slot的地方做交易(一手交錢,一手交貨),過程分以下步驟:

1。我先到一個叫做Slot的交易場所交易,發現你已經到了,那我就嘗試喊你交易,如果你迴應了我,決定和我交易那麼進入第2步;如果別人搶先一步把你喊走了,那我就進入第5步。


2。我拿出錢交給你,你可能會接收我的錢,然後把貨給我,交易結束;也可能嫌我掏錢太慢(超時)或者接個電話(中斷),TM的不賣了,走了,那我只能再找別人買貨了(從頭開始)。


3。我到交易地點的時候,你不在,那我先嚐試把這個交易點給佔了(一屁股做凳子上…),如果我成功搶佔了單間(交易點),那就坐這兒等著你拿貨來交易,進入第4步;如果被別人搶座了,那我只能在找別的地方兒了,進入第5步。


4。你拿著貨來了,喊我交易,然後完成交易;也可能我等了好長時間你都沒來,我不等了,繼續找別人交易去,走的時候我看了一眼,一共沒多少人,弄了這麼多單間(交易地點Slot),太TM浪費了,我喊來交易地點管理員:一共也沒幾個人,搞這麼多單間兒幹毛,給哥撤一個!。然後再找別人買貨(從頭開始);或者我老大給我打了個電話,不讓我買貨了(中斷)。


5。我跑去喊管理員,尼瑪,就一個坑交易個毛啊,然後管理在一個更加開闊的地方開闢了好多個單間,然後我就挨個來看每個單間是否有人。如果有人我就問他是否可以交易,如果迴應了我,那我就進入第2步。如果我沒有人,那我就佔著這個單間等其他人來交易,進入第4步。 


6。如果我嘗試了幾次都沒有成功,我就會認為,是不是我TM選的這個單間風水不好?不行,得換個地兒繼續(從頭開始);如果我嘗試了多次發現還沒有成功,怒了,把管理員喊來:給哥再開一個單間(Slot),加一個凳子,這麼多人就這麼幾個破凳子夠誰用!