使用future實現內建非同步API
當設計併發策略時,要將 "what做什麼"和 "how怎麼做"進行分離,
如果DoSomething 將花費很長時間執行,無論它是否耗費CPU,比如從資料庫中載入一個資料就是很耗費時間的,那麼是不是在DoSomething執行的同時,我們做做其他事情呢?
比如:
如果OtherWork不依賴result 這個值,那麼我們讓DoSomething使用通常意義上的非同步執行就沒有問題。
但是如果OtherWork依賴上一步執行結果result,怎麼辦?
第一個方案是使用Begin/End 模式實現:
設計一個開始介面,如下
再設計一個結果介面,如下:
使用方式如下程式碼:
這個模式需要在最後等待,無論DoSomething和OtherWork哪個先做完,都要等待對方,這個效能會很差,當然該文從.NET框架等多個角度說明這個模式一些侷限,這裡不再引述,可以參考原文。
我們主要目的是要將“如何非同步執行這個工作 ”(也就是呼叫"how如何做")和做什麼分離開來。在上面這個案例中,我們關注的是讓DoSomething和OtherWork非同步啟動,而DoSomething如何非同步執行(how),應該不是我們關心的,至少應該從上面這段呼叫程式碼中分離出去。而 begin/end 模式並沒有幫助我們做到這點,相反是將How和What耦合在一起了。
讓我們來看看如何實現How和What分離解耦:
1.使用一個分離的Task任務呼叫來執行How的工作內容,根據你的語言平臺,比如如果是Java/.NET,使用pool.run( /*task*/ ),如果C++0x,使用async( /*task*/ ) .
2.使用futures來管理非同步執行的結果. 這實際就是類Java JDK中的Future<T> API, C++0x標準即將也會有,而.NET下一個版本使用的是Task<T>.
這樣,上面案例程式碼如下:
這裡程式碼為什麼和前面程式碼不完全一致,因為我們根據How和What分離,更改了設計,如果前面案例的otherwork依賴DoSomething的結果,那麼,我們就要將otherwork內容進行分解,將otherwork中不依賴DoSomething結果的內容首先執行,也就是上面第二步,然後,使用在第三步,我們將兩個計算結果融合。
這種使用Future特性將How和What分離的模式,已經被使用在JdonFramework 6.2的Domain Events,實際就是Domain Events的內在機制,當領域模型中啟用一個事件時,實際就是傳送了一個訊息,在JdonFramework中,監聽訊息實際執行如下程式碼:
應該說:JdonFramework 6.2是將EDA和Java平行計算,非同步可伸縮性融合在一起,在設計理念是先進的,本文也可以驗證這點。參考Domain Events非同步應用
Prefer Futures to Baked-In "Async APIs"一文介紹瞭如何使用語言的並行API透過非同步來實現這點。
普通同步性質的方法如下:
RetType DoSomething( InParameters ins, OutParameters outs ); <p class="indent"> |
如果DoSomething 將花費很長時間執行,無論它是否耗費CPU,比如從資料庫中載入一個資料就是很耗費時間的,那麼是不是在DoSomething執行的同時,我們做做其他事情呢?
比如:
result = DoSomething( this, that, outTheOther ); OtherWork(); <p class="indent"> |
如果OtherWork不依賴result 這個值,那麼我們讓DoSomething使用通常意義上的非同步執行就沒有問題。
但是如果OtherWork依賴上一步執行結果result,怎麼辦?
第一個方案是使用Begin/End 模式實現:
設計一個開始介面,如下
IAsyncResult BeginDoSomething( InParameters ins ); <p class="indent"> |
再設計一個結果介面,如下:
RetType EndDoSomething( IAsyncResult asyncResult,//上一介面計算的結果 OutParameters outs ); <p class="indent"> |
使用方式如下程式碼:
IAsyncResult ar = BeginDoSomething( this, that ); result = DoSomething( this, that, outTheOther ); //在DoSomething執行同時,執行OtherWork OtherWork(); //將上面兩個融合Join, ar.AsyncWaitHandle.WaitOne();//必要時需要等待 result = EndDoSomething( ar, outtheOther ); <p class="indent"> |
這個模式需要在最後等待,無論DoSomething和OtherWork哪個先做完,都要等待對方,這個效能會很差,當然該文從.NET框架等多個角度說明這個模式一些侷限,這裡不再引述,可以參考原文。
我們主要目的是要將“如何非同步執行這個工作 ”(也就是呼叫"how如何做")和做什麼分離開來。在上面這個案例中,我們關注的是讓DoSomething和OtherWork非同步啟動,而DoSomething如何非同步執行(how),應該不是我們關心的,至少應該從上面這段呼叫程式碼中分離出去。而 begin/end 模式並沒有幫助我們做到這點,相反是將How和What耦合在一起了。
讓我們來看看如何實現How和What分離解耦:
1.使用一個分離的Task任務呼叫來執行How的工作內容,根據你的語言平臺,比如如果是Java/.NET,使用pool.run( /*task*/ ),如果C++0x,使用async( /*task*/ ) .
2.使用futures來管理非同步執行的結果. 這實際就是類Java JDK中的Future<T> API, C++0x標準即將也會有,而.NET下一個版本使用的是Task<T>.
這樣,上面案例程式碼如下:
//第一步 asynchronous call future<int> result = async( ()=<{ return CallSomeFunc(x,y,z); } ); //第二步 code here runs concurrently with CallSomeFunc //同時執行其他事情 //第三步 use result when it's ready (this might block) //在這裡使用非同步執行dosomething的結果 DoSomethingWith( result.value() ); <p class="indent"> |
這裡程式碼為什麼和前面程式碼不完全一致,因為我們根據How和What分離,更改了設計,如果前面案例的otherwork依賴DoSomething的結果,那麼,我們就要將otherwork內容進行分解,將otherwork中不依賴DoSomething結果的內容首先執行,也就是上面第二步,然後,使用在第三步,我們將兩個計算結果融合。
這種使用Future特性將How和What分離的模式,已經被使用在JdonFramework 6.2的Domain Events,實際就是Domain Events的內在機制,當領域模型中啟用一個事件時,實際就是傳送了一個訊息,在JdonFramework中,監聽訊息實際執行如下程式碼:
private void asynExecMessageListener(final DomainMessage message) { FutureTask futureTask = new FutureTask(new Callable<Boolean>() { public Boolean call() throws Exception { try { message.getMessageListener().action(message); } catch (Exception e) { .... return true; } }); message.addFutureTask(futureTask);//執行futuretask executor.execute(futureTask);//相當於pool.run } <p class="indent"> |
應該說:JdonFramework 6.2是將EDA和Java平行計算,非同步可伸縮性融合在一起,在設計理念是先進的,本文也可以驗證這點。參考Domain Events非同步應用
[該貼被admin於2010-01-20 09:22修改過]
相關文章
- Spring Boot使用@Async實現非同步呼叫:使用Future以及定義超時Spring Boot非同步
- 構建api gateway之 基於etcd實現動態配置同步APIGateway
- flutter實戰5:非同步async、await和Future的使用技巧Flutter非同步AI
- python中非同步非阻塞如何實現Python非同步
- Rust非同步之FutureRust非同步
- node常用內建apiAPI
- python內建方法APIPythonAPI
- 9.2 運用API實現執行緒同步API執行緒
- tornado原理介紹及非同步非阻塞實現方式非同步
- Flutter - 內建動畫 APIFlutter動畫API
- 非框架內使用 ORM框架ORM
- 使用 Vert.X Future/Promise 編寫非同步程式碼Promise非同步
- 構建api gateway之 http路由實現APIGatewayHTTP路由
- 使用async實現非同步控制非同步
- `std::future`--非同步的優勢非同步
- Flutter非同步程式設計-FutureFlutter非同步程式設計
- PHP內建字串函式實現PHP字串函式
- 視覺化搭建內建 API視覺化API
- future promise shared_future簡單使用Promise
- Netty非同步Future原始碼解讀Netty非同步原始碼
- 用匿名內部類實現 Java 同步回撥Java
- 突破Android P非SDK API限制的幾種程式碼實現AndroidAPI
- 【Flutter 專題】91 圖解 Dart 單執行緒實現非同步處理之 Future (二)Flutter圖解Dart執行緒非同步
- 同步非同步,阻塞非阻塞非同步
- 非同步、同步、阻塞、非阻塞非同步
- 基於Guava API實現非同步通知和事件回撥GuavaAPI非同步事件
- Java非同步之《我call(),Future在哪裡》Java非同步
- Android中實現錄製內建聲音Android
- 利用 PHP 反射實現內建函式文件PHP反射函式
- 使用frp實現內網穿透FRP內網穿透
- 同步、非同步,阻塞、非阻塞理解非同步
- 同步、非同步、阻塞與非阻塞非同步
- 同步非同步 與 阻塞非阻塞非同步
- 理解阻塞、非阻塞、同步、非同步非同步
- SpringBoot使用Swagger2實現Restful APISpring BootSwaggerRESTAPI
- 使用Task實現非阻塞式的I/O操作
- 使用PHP內建web伺服器,實現簡單的除錯應用PHPWeb伺服器除錯
- 混合高斯模型實現運動目標檢測(OpenCV內建實現)模型OpenCV
- Linux檢視內建命令和非內建命令幫助的幾種方法(man、help、info)Linux