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方法組織真實業務資料;