1. 程式人生 > >java執行緒深度解析(三)——併發模型(Future)

java執行緒深度解析(三)——併發模型(Future)

Main:啟動系統,呼叫Client發出請求;

Client:返回Data物件,理解返回FutureData,並開啟ClientThread執行緒裝配RealData;

Data:返回資料的介面;

FutureData:Future資料,構造很快,但是是一個虛擬的資料,需要裝配RealData;

RealData:真實資料,構造比較慢。

(1)Data介面 ,提供getResult方法

public interface Data {
	public String getResult();
}

(2)Future類實現,RealData的代理類,用於返回RealData的包裝物件,封裝了RealData的等待過程

/*
 * 實現了一個快速返回RealData 的包裝,但並非真實的返回結果。
 */
public class FutureData  implements Data{
	protected RealData realData=null; //FutureData是RealData的一個包裝
	protected boolean isReady=false;
	public synchronized void setRealData(RealData realData)
	{
		if(isReady)
		{
			return;
		}
		this.realData=realData;
		isReady=true;
		notifyAll(); //當呼叫Future包裝類的set方法時,執行緒RealData被喚醒,同個getResult()方法
	}

	@Override
	public synchronized String getResult() { //會等待RealData構造完成
		while(!isReady)
		{
			try{
				wait(); //一直等待,直到RealData被注入
			}catch (Exception e)
			{}
		}
		return realData.result; //RealData的真實實現
	}
}

(3)RealData類實現

public class RealData  implements Data{
	protected  final String result;
	public RealData(String para)
	{
		StringBuffer sb=new StringBuffer();
		//模擬一個很慢的構造過程
		for(int i=0;i<50;i++)
		{
			sb.append(para);
			try {
				Thread.sleep(100);//代替一個很慢的操作過程
			} catch (Exception e) {
				
			}
		}
		result=sb.toString();
	}
	public String getResult()
	{
		return result;
	}
}

(4)Client實現,用於獲取FutureData,開啟RealData執行緒,在接收請求後,快速返回future

public class Client  
{
	public Data request(final String queryString)
	{
		final FutureData future=new FutureData();
		new Thread() //RealData構建很慢,放到一個單獨的執行緒中進行
		{
			public void run() {
				RealData realData=new RealData(queryString);
				future.setRealData(realData);
			       //呼叫future的set方法,直接return 並喚醒RealData執行緒進行資料構造};
		}.start();
		return future;  //立即被返回
	}
}

(5) Main方法實現

/*
 * 主要負責呼叫client發起請求,並使用返回的資料
 */
public class Main  {
	public static void main(String[] args) {
		Client client =new Client();
		//這裡會立即返回結果,因為得到的是FutureData 而非RealData
		Data data=client.request("name");
		System.out.println("請求完畢!");
		System.out.println(data.toString());
		
		try{
			//代表對其他業務的處理
			//在處理過程中,RealData被傳劍,充分利用了等待時間
			//Thread.sleep(2000);
			System.out.println("我也在被處理哦");
		}catch(Exception e)
		{}
		System.out.println("真實資料:"+data.getResult());
	}
}

最後程式輸出:

請求完畢!
[email protected] --future物件
我也在被處理哦  --其他業務處理結果
真實資料:namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename

     3、Future模式總結

      Future模式的核心在於去除了main函式中的等待時間,使得原本等待的時間用於處理其他業務,充分利用計算機資源。

      主要通過代理future類實現和RealData同樣的介面實現,所以在main呼叫getResult時兩個類對於main呼叫是一樣的,因為future中的執行緒wait,返回future資料後,喚醒執行緒,例項化RealData時呼叫構造方法,組裝資料返回。在此過程中main利用等待時間呼叫其它業務方法。 在類似於商品購買等業務中Future模式應用廣泛。

      一句話總結:精彩無需等待,西瓜太大先撿著芝麻等西瓜。

二、JDK1.6的內建Future實現

     在JDK原始碼中,關於併發的實現concurrent 包中,Future介面提供執行緒控制:取消任務、返回物件、設定超時時間,同樣一個RealData類實現該介面,提供call方法組織真實業務資料;