多執行緒的設計模式---future模式1
Future模式是多執行緒開發中非常常見的一種設計模式,它的核心思想是非同步呼叫。這類似我們日常生活中的線上購物流程,帶在購物網看著一件商品時可以提交表單,當訂單完成後就可以在家裡等待商品送貨上門。或者說更形象的是我們傳送Ajax請求的時候,頁面是非同步的進行後臺處理,使用者無需等待請求的結果,可以繼續瀏覽或操作其他內容。
如上圖所示,客戶端呼叫購物請求,服務端程式不等資料處理完成便立即返回客戶端一個偽造的資料,(相當於訂單,而不是真實的商品)這時候由服務端自己偷偷摸摸的傳送了一個other call()請求去獲取真實的商品(打包,出庫,送貨)。這就是Future模式的核心所在。
Future模式的主要角色有:
Main:系統啟動,呼叫FutureClient發出請求
FutureClient:返回Data物件,立即返回FutureData,並開啟執行緒去獲取RealData
Data:返回資料的介面
FutureData:虛擬資料,返回很快,需要裝載RealData
RealData:真實資料
下面上程式碼:
Main:
public class TestFuture { public static void main(String[] args) { FutureClient fc = new FutureClient(); Data data = fc.getRequset("jianzh5"); System.out.println("請求完畢..." + new Date()); String result = data.getRequest(); System.out.println("0000000000000"); System.out.println("返回的結果:" + result + "-------------" + new Date()); } }
此類主要呼叫FutureClient的getRequset方法去返回資料
FutureClient:
public class FutureClient { public Data getRequset(final String queryStr){ //初始化代理物件,先返回給客戶端 final FutureData futureData = new FutureData(); //啟動一個新的執行緒去載入真實的資料,傳遞給這個代理物件 new Thread(new Runnable() { @Override public void run() { //此執行緒去載入真實物件,然後傳遞給代理物件 RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); System.out.println("代理物件返回:"+futureData); return futureData; } }
該類在接受到使用者請求後很快就能返回虛擬資料 futureData,本身啟動一個執行緒去獲取真實資料
RealData:
public class RealData implements Data{
private String result;
public RealData(String queryStr){
System.out.println("根據引數: "+queryStr+" 進行查詢,這是一個很耗時的操作!");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("裝載完畢,獲取結果");
result = "查詢結果";
}
@Override public String getRequest() {
return result;
}
}
RealData裝載資料較慢,這裡使用Sleep(5000)模擬複雜業務邏輯。
FutureData:
public class FutureData implements Data{
private RealData realData;
private boolean isReady = false;
public synchronized void setRealData(RealData realData){
//如果已經裝載完畢則直接返回
if(isReady){
return;
}
//如果未裝載,進行裝載真實資料
this.realData = realData;
isReady = true;
//通知
notify();
}
@Override public synchronized String getRequest() {
//如果未裝載好一直處於阻塞狀態
while (!isReady){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//裝載好直接返回資料即可
return this.realData.getRequest();
}
}
該類是Future模式的關鍵,它實際是真實資料RealData的代理,封裝了獲取RealData的等待過程實際返回的是真實的資料。
下面是程式的輸出:
代理物件返回:[email protected]
根據引數: jianzh5 進行查詢,這是一個很耗時的操作!
請求完畢...Wed Nov 21 10:37:29 CST 2018
裝載完畢,獲取結果
0000000000000
返回的結果:查詢結果-------------Wed Nov 21 10:37:34 CST 2018
由列印結果可以看出,程式還是會在 "String result = data.getRequest();" 這行停止一段時間的