使用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異步調用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM