深入理解[Future模式]原理與技術
1.Future模式
Future模式和多執行緒技術密切相關,可以說是利用多執行緒技術優化程式的一個例項。
在程式設計中,當某一段程式提交了一個請求,期望得到一個答覆。但非常不幸的是,服務程式對這個請求的處理可能比較慢,比如,這個請求可能是通過網際網路、HTTP或者Web Service等並不高效的方式呼叫的。在傳統的單執行緒環境下,呼叫函式是同步的,也就是說它必須等到服務程式返回結束後,才能進行其他處理。而在Future模式下,呼叫方式改為非同步的,而原先等待返回的時間段,在主呼叫函式中,則可能用於處理其它事務。示例程式:
(1)Main方法的實現
main方法主要負責呼叫Client發起請求,並使用返回的資料:
public class Future {
public static void main(String[] args) {
Client client = new Client();
Data data = client.request("name");
System.out.println("請求完畢 "+System.currentTimeMillis());
//...這裡做一些其它任務
System.out.println("資料:"+data.getResult());
System.out.println("獲取完畢 "+System.currentTimeMillis());
}
}
(2)Client的實現
client主要實現了獲取FutureData,開啟構造RealData的執行緒,並在接受請求後,很快的返回FutureData。
public class Client {
public Data request(String queryStr){
FutureData futureData = new FutureData();
new Thread(new Runnable() {
@Override
public void run() {
RealData realData = new RealData(queryStr);
futureData.setRealData(realData);
}
}).start();
return futureData;
}
}
(3)Data的實現
Data是一個介面,提供了getResult()方法。
public interface Data {
String getResult();
}
(4)FutureData的實現
FutureData 實現了一個快速返回的RealData 包裝。它只是一個包裝,或者說是一個RealData 的虛擬實現 。因此,它可以很快被構造並返回。當使用FutureData的getResult()方法時,程式會阻塞,等待RealData()被注入到程式中,才使用RealData的getResult()方法返回。
public class FutureData implements Data {
private RealData realData = null;
private boolean isReady = false;
synchronized public void setRealData(RealData realData){
if (isReady){
return;
}
this.realData = realData;
isReady = true;
notifyAll(); //通知所有等待的執行緒繼續執行
}
@Override
synchronized public String getResult() {
while (!isReady){
try {
System.out.print("...waiting...");
wait(); //使當前執行緒在此處進行等待,直到被通知後繼續執行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.result;
}
}
(5)RealData 的實現
RealData 是最終需要使用的資料模型,它的構造很慢。在這裡,使用sleep()函式模擬這個過程。
public class RealData implements Data {
protected String result;
public RealData(String para) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = "["+para+"]";
}
@Override
public String getResult() {
return result;
}
}
執行結果:
請求完畢 1537520554813
...waiting...
資料:[name]
獲取完畢 1537520555890
程式執行的流程是Main執行緒去獲取資料,但是資料還在處理中,於是Main執行緒進入等待狀態,當資料處理完並通知等待所有等待的執行緒之後,Main執行緒得以繼續執行下去。
2.JDK的內建實現
Future模式如此常用,以至於在JDK的併發包中,就已經內建了一種Future模式的實現了。
示例程式:
public class RealData implements Callable<String> {
private String para;
public RealData(String para) {
this.para = para;
}
@Override
public String call() throws Exception {
//這裡是真實的業務邏輯
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "["+para+"]";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//傳入RealData到FutureTask
FutureTask<String> futureTask = new FutureTask<String>(new RealData("name"));
//建立一個執行緒池
ExecutorService executorService = Executors.newFixedThreadPool(1);
//在這裡開啟執行緒執行RealData的call()方法
executorService.submit(futureTask);
System.out.println("請求完畢 "+System.currentTimeMillis());
//...這裡進行一些其它操作
System.out.println("資料:"+futureTask.get());
System.out.println("獲取完畢 "+System.currentTimeMillis());
//啟動一個有序的關閉,之前提交的任務將被執行,但是不會接受新的任務。
executorService.shutdown();
}
}
執行結果:
請求完畢 1537521833970
資料:[name]
獲取完畢 1537521834977
Callable介面是一個使用者自定義實現的介面。在應用程式中,通過實現Callable介面的call()方法,指定FutureTask的實際內容和返回物件。
Future介面提供的執行緒控制功能有:
//取消任務
boolean cancel(boolean mayInterruptIfRunning)
//是否已經取消
boolean isCancelled()
//是否已經完成
boolean isDone()
//取得返回物件
V get() throws InterruptedException, ExecutionException
//取得返回物件,可以設定超時時間
V get(long timeout, TimeUnit unit)
總結
Future模式的核心在於去除了主函式中的等待時間,並使得原來需要等待的時間段可以用於處理其他的業務邏輯,從而充分利用計算機資源。
作者:像風一樣
相關文章
- 深入理解[觀察者模式]原理與技術模式
- 深入理解Sora技術原理|得物技術Sora
- 【得物技術】深入理解synchronzied底層原理
- Flutter之Future原理解析Flutter
- 深入理解冪等技術
- Babel 外掛原理的理解與深入Babel
- 深入理解零拷貝技術
- Docker | Docker技術基礎梳理(四) - 深入理解映象與容器Docker
- 一文深入理解快照技術
- 深入理解 ProtoBuf 原理與工程實踐(概述)
- Future模式模式
- 快速理解容器技術的實現原理
- 深入理解代理模式模式
- 深入淺出理解 Spark:環境部署與工作原理Spark
- 深入理解flutter的編譯原理與優化Flutter編譯原理優化
- 理解「業務」與「技術」概念
- 深入理解HTTPS工作原理HTTP
- HDC技術分論壇:ArkCompiler原理解析Compile
- 筆記 深入探索Android熱修復技術原理筆記Android
- 深入理解工廠模式模式
- 深入理解單例模式單例模式
- 深入理解中文編碼:原理、應用與實踐
- 架構師日記-深入理解軟體設計模式 | 京東雲技術團隊架構設計模式
- 深入理解Argo CD工作原理Go
- 深入理解:Spring MVC工作原理SpringMVC
- Future 模式之 CompletableFuture模式
- 深入理解DES演算法:原理、實現與應用演算法
- 【深入理解Go】協程設計與排程原理(下)Go
- 【深入理解Go】協程設計與排程原理(上)Go
- Future和CompletableFuture的理解
- MVC設計模式深入理解MVC設計模式
- 深入原始碼理解Spring整合MyBatis原理原始碼SpringMyBatis
- 深入理解React:事件機制原理React事件
- 深入理解 MySQL 索引底層原理MySql索引
- 深入理解瀏覽器工作原理瀏覽器
- 深入理解 Spring 的事務原理Spring
- 深入理解Android逆向除錯原理Android除錯
- 深入理解ReentrantLock的實現原理ReentrantLock