Future模式理解及FutureTask應用場景
阿新 • • 發佈:2018-04-16
返回 重點 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 = falseView Code; 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; } }
首先我們要明確,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應用場景