在开发中会碰到一种场景,如下
Object result1 = service1.func1();//执行80ms
Object result2 =service2.func2();//执行50ms service3.func3(result1,result2);
func3()需要等待func1和func2的执行结果。总共需要等待130ms.如果能够让func1和func2同时执行,那么最少的等待时间将会是80ms.
下面使用CompletableFuture来实现。
JDK1.8才新加入的一个实现类CompletableFuture
,实现了Future<T>
, CompletionStage<T>
两个接口。
定义任务类
这里定义了一个方法findUser,它的返回值是CompletableFuture<String>,用来模拟远程调用。
当执行结果是正常时,通过
public boolean complete(T value)
返回结果。
当执行异常时,如果想向调用者返回异常,通过
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异步调用。