天天看點

多線程設計模式 - Future模式

概述

Future模式是多線程開發中非常常見的一種設計模式,它的核心思想是異步調用。這類似我們日常生活中的線上購物流程,帶在購物網看着一件商品時可以送出表單,當訂單完成後就可以在家裡等待商品送貨上門。或者說更形象的是我們發送Ajax請求的時候,頁面是異步的進行背景處理,使用者無需等待請求的結果,可以繼續浏覽或操作其他内容。

多線程設計模式 - Future模式

如上圖所示,用戶端調用購物請求,服務端程式不等資料處理完成便立即傳回用戶端一個僞造的資料,(相當于訂單,而不是真實的商品)這時候由服務端自己偷偷摸摸的發送了一個other call()請求去擷取真實的商品(打包,出庫,送貨)。這就是Future模式的核心所在。

Future模式的主要角色有:

Main:系統啟動,調用FutureClient送出請求

FutureClient:傳回Data對象,立即傳回FutureData,并開啟線程去擷取RealData

Data:傳回資料的接口

FutureData:虛拟資料,傳回很快,需要裝載RealData

RealData:真實資料

代碼實戰

根據上面的介紹我們用代碼來模拟一下具體的實作過程:

Main:

public class Main {    public static void main(String[] args) {        FutureClient fc = new FutureClient();        Data data = fc.getRequset("jianzh5");        System.out.println("請求完畢...");        String result = data.getRequest();        System.out.println("傳回的結果:"+result);    }}      

此類主要調用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的等待過程實際傳回的是真實的資料。

其實在JDK内部類已經實作了Future模式,詳細内容我們下期再聊!