Future模式是一種很是常見的設計模式,其核心思想就是異步調用。設計模式
參與者 | 做用 | 備註 |
---|---|---|
Main | 系統啓動,調用client發出請求 | 能夠看作是一個應用 |
client | 用於返回Data對象,當即返回FutureData,並開啓一個線程裝配RealData | |
Data | 返回數據的接口 | |
FutureData | FutureData實現了Data接口,構造很快,是一個虛擬數據,須要裝配RealData真實數據 | 也能夠看作是構造一個空的Data對象,按字面意思來看就是未來的數據,尚未...,當客戶端須要使用數據時須要設置成RealData對象 |
RealData | 真實數據,起構造可能會比較慢,RealData也實現了Data接口 | 這個數據纔是Main應用須要的 |
/** * Created with IntelliJ IDEA. * User: * Date: 2018/12/29 * Time: 下午6:47 * Description: Data接口有兩個重要的實現,FutureData和RealData,RealData表明的是真實數據,FutureData是真實數據的代理或者說是包裝 */ public interface Data { String getResult(); }
/** * Created with IntelliJ IDEA. * User: * Date: 2018/12/29 * Time: 下午6:44 * Description: 實現Data接口,其功能是對RealData進行包裝、代理,在FutureClient請求Data數據時,將當即返回一個包裝好的虛擬數據(RealData的虛擬數據) */ public class FutureData implements Data { //既然FutureData是RealData對象的包裝,那麼久應該有一個對象的引用 private RealData realData = null; //標註真實數據是否準備好 private boolean isReady = false; //取數據時,若是RealData還沒注入數據,則將阻塞等待 private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void setRealData(RealData realData) { while (isReady) { //數據已經準備好,直接退出 return; } lock.lock(); try { this.realData = realData; this.isReady = true; //數據已經準備,通知阻塞在getResult()上的請求 condition.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } /** * 獲取真實數據,若是RealData代理對象沒有準備好數據,則阻塞 * * @return */ public String getResult() { lock.lock(); try { while (!isReady) { //釋放鎖,同時阻塞 condition.await(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } return realData.result; } }
/** * Created with IntelliJ IDEA. * User: zhouyonggui * Date: 2018/12/29 * Time: 下午6:54 * Description: RealData是最終須要使用的數據,須要返回給FutureData */ public class RealData implements Data { protected String result = null; /** * 在這個過程當中,模擬數據包裝 * * @return */ public RealData(String param) { StringBuffer sb = new StringBuffer(); //假設須要很長時間的業務處理 for (int i = 0; i < 10; i++) { sb.append(param); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } result = sb.toString(); } public String getResult() { return result; } }
接下來就是client,內部主要實現了FutureData,並開啓一個線程去構造RealData。在接受請求後,先返回一個FutureData對象,此時FutureData內部並無真實數據,在須要使用數據時須要等待RealData構造完成,此時若是數據還沒有準備好,則將阻塞直到有數據返回。app
/** * Created with IntelliJ IDEA. * User: zyg * Date: 2019/1/2 * Time: 下午9:12 * Description:FUture客戶端主要負責獲取FutureData,並異步起一個線程,構造RealData */ public class Client { public Data request(final String queryStr) { final FutureData future = new FutureData(); new Thread(new Runnable() { public void run() { RealData realData = new RealData(queryStr); future.setRealData(realData); } }).start(); return future; } }
最後是咱們的Main應用,她主要是負責調用client發起請求,並消費返回的數據。異步
/** * Created with IntelliJ IDEA. * User: zyg * Date: 2019/1/2 * Time: 下午9:21 * Description: */ public class Main { public static void main(String[] args) { Client client = new Client(); //客戶端發起請求 Data data = client.request("楊冪"); System.out.println("客戶端請求完畢!"); //模擬其餘業務 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //使用真實數據 System.out.println("數據=" + data.getResult()); } }