1. 程式人生 > >Future模式理解及FutureTask應用場景

Future模式理解及FutureTask應用場景

返回 重點 urn sys exce 阻塞 for 來看 all

一、 Future模式理解

先說一下為什麽要用future模式:兩個任務沒有必然的前後關系,如果在一個線程中串行執行,就有些浪費時間,不如讓兩個線程去並行執行這兩個任務,執行完了到主線程去匯報就可以了。(讓任務後臺運行,不阻塞線程)

則使用Future模式耗費的時間為: max(TimeofTask1,TimeofTask2)。串行的話則是TimeofTask1+TimeofTask2。

接下來使用代碼的類圖:

技術分享圖片

先貼出源碼,可以先看下源碼理解一下,怎麽使用就成了future模式。

Interface:

public interface Data {
    public String getResult();
}

RealData:

public class RealData implements Data{
    protected final String result;

    public RealData(String para) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(para);
        }
        try {
            // 這裏使用sleep,模擬很慢的構造RealData過程
Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } result = sb.toString(); } }

FutureData

技術分享圖片
// FutureData是RealData的包裝
public class FutureData implements Data {
    protected RealData realData = null;
    protected boolean isReady = false
; public synchronized void setRealData(RealData realdata){ if (isReady){ return; } this.realData = realdata; isReady = true; // RealData註入完畢以後,通知getResult() notifyAll(); } @Override public synchronized String getResult() { while (!isReady){ try { // 等待RealData被註入,直到被notify wait(); } catch (InterruptedException e) { e.printStackTrace(); } } return realData.result; } }
View Code

首先我們要明確,RealData是我們真正需要的數據,FutureData只是做了一層封裝,可以實現在得到RealData的過程中不阻塞當前線程。

我們重點來看FutureData,就兩個方法,暫且把setRealData叫做註入數據方法,getResult是拿到最終數據方法。

一個狀態位isReady,等待RealData註入完畢,就可以getResult了。沒註入完畢,則阻塞當前線程。

有了這些信息,我們可以這樣想,這個構建RealData很費時間,不如把這個構建任務扔到一個線程裏去,當前線程去做其他事情。

使用方法:

public class FutureMainByMyself {
    public Data request(final String queryStr){
        // futureData包裝了RealData
        final FutureData futureData = new FutureData();
        new Thread(){
            // RealData構建很慢,放在一個線程裏慢慢去構建
            @Override
            public void run() {
                RealData realData = new RealData(queryStr);
                futureData.setRealData(realData);
            }
        }.start();
        return futureData;
    }

    public static void main(String[] args) {
        FutureMainByMyself client = new FutureMainByMyself();
        Data data = client.request("name");
        System.out.println("請求完畢");
        //這裏才是真實的數據
        try {
            //這裏的sleep代表了其他的業務邏輯,
            //在處理這些業務邏輯的同時,RealData被創建,從而充分利用了時間
            System.out.println(LocalTime.now());
            Thread.sleep(2000);
            System.out.println(LocalTime.now());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("數據=" +data.getResult() + " " + LocalTime.now());

    }
}

二、FutureTask應用場景和源碼解析

FutureTask使用場景上面只是大致說了一下,下面我們來舉一個具體的場景:API網關。

技術分享圖片

比方說用戶打開一個訂單頁面:可能要查許多接口:訂單信息,積分信息,退換貨信息,這時候如果串行去查這麽多東西,很費時間。

這些信息是沒有必要的先後關系的,所以可以做出並行的。平時我們用軟件也能註意到,先出來這塊信息,再出來那塊信息,這就是並行去查的結果,當然也可以等所有信息都拿到,再同時返回。

技術分享圖片

FutureTask源碼解析:

Future模式理解及FutureTask應用場景