使用CompletableFuture实现异步编程

 

在开发中会碰到一种场景,如下

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异步调用。

 

posted @ 2019-04-29 15:57  冬眠的山谷  阅读(3298)  评论(0编辑  收藏  举报