1. 程式人生 > >多執行緒的設計模式---future模式1

多執行緒的設計模式---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();" 這行停止一段時間的