Future模式模擬
阿新 • • 發佈:2019-01-25
err data 很快 處理 image scrip 通知 51cto ted Future模式是一種非常常見的設計模式,其核心思想就是異步調用。
1. Future模式的主要參與者
參與者 | 作用 | 備註 |
---|---|---|
Main | 系統啟動,調用client發出請求 | 可以看做是一個應用 |
client | 用於返回Data對象,立即返回FutureData,並開啟一個線程裝配RealData | |
Data | 返回數據的接口 | |
FutureData | FutureData實現了Data接口,構造很快,是一個虛擬數據,需要裝配RealData真實數據 | 也可以看做是構造一個空的Data對象,按字面意思來看就是將來的數據,還沒有...,當客戶端需要使用數據時需要設置成RealData對象 |
RealData | 真實數據,起構造可能會比較慢,RealData也實現了Data接口 | 這個數據才是Main應用需要的 |
2. Future模式流程圖如下:
3. Future模式的簡單實現
3.1 核心接口Data
/** * 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構造完成,此時如果數據尚未準備好,則將阻塞直到有數據返回。
/**
* 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());
}
}
Future模式模擬