在開發中會碰到一種場景,以下html
Object result1 = service1.func1();//執行80ms Object result2 =service2.func2();//執行50ms service3.func3(result1,result2);
func3()須要等待func1和func2的執行結果。總共須要等待130ms.若是可以讓func1和func2同時執行,那麼最少的等待時間將會是80ms.
java
下面使用CompletableFuture來實現。apache
JDK1.8才新加入的一個實現類CompletableFuture
,實現了Future<T>
, CompletionStage<T>
兩個接口。異步
定義任務類 async
這裏定義了一個方法findUser,它的返回值是CompletableFuture<String>,用來模擬遠程調用。ide
當執行結果是正常時,經過spa
public boolean complete(T value)線程
返回結果。code
當執行異常時,若是想向調用者返回異常,經過htm
public boolean completeExceptionally(Throwable ex)
返回異常。
class TaskService{ public CompletableFuture<String> findUser(){ CompletableFuture<String> future = new CompletableFuture(); //模仿遠程調用線程 new Thread(){ @Override public void run() { String result = null; System.out.println("任務開始執行...."); try{ Thread.sleep(3000); //模仿RPC遠程調用 result = rpcRequest(true); System.out.println("任務執行結束...."); } catch(Exception ex){ future.completeExceptionally(ex); } future.complete(result); } }.start(); 直接返回future. return future; } /** *功能描述 * @author lgj * @Description 模仿RPC遠程調用 * @date 4/29/19 * @param: flag true:返回正常結果 false:拋出異常 * * @return: * */ public String rpcRequest(boolean flag){ String result = null; if(flag){ result = "libai"; } else { throw new NullPointerException(); } return result; } }
主線程調用
public class CompletableFutureDemo { public static void main(String args[]){ TaskService service = new TaskService(); CompletableFuture<String> future = service.findUser(); future.whenComplete((t,u)->{ if(u != null){ System.out.println("異步調用發生異常:" + u); } else { System.out.println("異步調用執行正常: " + t); } }); System.out.println("主線程任務執行完畢"); } }
主線程經過whenComplete來回調結果。這裏須要經過lambada 表達式來獲取結果
public CompletableFuture<T> whenComplete( BiConsumer<? super T, ? super Throwable> action) { return uniWhenCompleteStage(null, action); }
當結果正常時
任務開始執行....
主線程任務執行完畢
任務執行結束....
異步調用執行正常: libai
當調用發生異常時
任務開始執行....
主線程任務執行完畢
異步調用發生異常:java.lang.NullPointerException
以上,便實現了異步調用。
目前,dubbo-2.7.0+即是使用CompletableFuture來實現rpc異步調用。