什么是future模式呢?解釋這個概念之前我們先來了解一個場景吧,財務系統的結賬功能,這個功能可能是每個月用一次,在這一個月中相關的數據量已經積累得非常大,這一個功能需要調用好幾個存儲過程來完成。假如要調用5個存儲過程,每個存儲過程要執行5分鍾左右,那么這5個加起來就要25分鍾。現在用戶要求優化,把結賬功能的時間控制在10分鍾之內,那么該怎么做呢?解決方案就是將5個存儲過程按照業務划分成幾個組,這幾個組並行執行。其實也就類似ajax的異步請求,主線程可以做其他的事情,耗時的業務讓子線程去完成,子線程完成后將數據放在指定的地方,主線程需要的時候再去指定的地方去拿數據。下面代碼中FutureData 巧妙地使用了wait和notify方法來保證數據的獲取與加載的協調性。
public class FutureClient { public Data request(final String queryStr){ //1 我想要一個代理對象(Data接口的實現類)先返回給發送請求的客戶端,告訴他請求已經接收到,可以做其他的事情 final FutureData futureData = new FutureData(); //2 啟動一個新的線程,去加載真實的數據,傳遞給這個代理對象 new Thread(new Runnable() { @Override public void run() { //3 這個新的線程可以去慢慢的加載真實對象,然后傳遞給代理對象 RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); return futureData; } }
public interface Data { String getRequest(); }
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(); } }
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; } }