1. 程式人生 > >初探 CompletableFuture Java8新的非同步程式設計方式

初探 CompletableFuture Java8新的非同步程式設計方式

  1. 序言

       由於專案中想獲取多個非同步執行緒的狀態,並判斷其是否都執行完成,若執行完成後則做後續操作,經同事提醒java8 中CompletableFuture這個可以完美解決專案問題,故藉此機會學習了下,記錄下涉及到的知識點,以便後期回顧。

  1. CompletableFuture

        2.1 Async結尾的方法都是可以非同步執行的,如果指定了執行緒池,會在指定的執行緒池中執行,如果沒有指定,預設會ForkJoinPool.commonPool()中執行。

     runAsync方法:它以Runnabel函式式介面型別為引數,所以CompletableFuture的計算結果為空。

    supplyAsync方法以Supplier<U>函式式介面型別為引數,CompletableFuture的計算結果型別為U。

方法    描述
static CompletableFuture<Void> runAsync(Runnable runnable) 返回一個新的CompletableFuture,它在執行給定操作後由執行在 ForkJoinPool.commonPool()中的任務 非同步完成
static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) 返回一個新的CompletableFuture,它在執行給定操作後在給定的執行緒池中執行的任務非同步完成非同步完成
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) 返回一個新的CompletableFuture,它通過在 ForkJoinPool.commonPool()中執行的任務與通過呼叫給定的供應商獲得的值 非同步完成
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) 返回一個新的CompletableFuture,由給定執行器中執行的任務非同步完成,並通過呼叫給定的供應商獲得的值
  //1. 返回一個新的CompletableFuture,它在執行給定操作後由執行在 ForkJoinPool.commonPool()中的任務 非同步完成。
        CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(()-> {
            System.out.println(" completableFuture1 is not nothing");
        });
        //2. 返回一個新的CompletableFuture,它在執行給定操作後在給定的執行緒池中執行的任務非同步完成非同步完成。
        CompletableFuture<Void> completableFuture2 = CompletableFuture.runAsync(()-> {
            System.out.println(" completableFuture2 is not nothing");
        },Executors.newSingleThreadExecutor());

       //3. 返回一個新的CompletableFuture,它通過在 ForkJoinPool.commonPool()中執行的任務與通過呼叫給定的供應商獲得的值 非同步完成。
        CompletableFuture<Object> completableFuture3 = CompletableFuture.supplyAsync(()-> {
                    return "hello completableFuture3";
                });
       //4. 返回一個新的CompletableFuture,由給定執行器中執行的任務非同步完成,並通過呼叫給定的供應商獲得的值。
        CompletableFuture<Object> completableFuture4 = CompletableFuture.supplyAsync(()-> {
            return "hello completableFuture4";
        },Executors.newSingleThreadExecutor());

        System.out.println(completableFuture3.get());
        System.out.println(completableFuture4.get());

   2.2 allOf 、 anyOf

方法 描述
static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) 返回一個新的CompletableFuture,當所有給定的CompletableFutures完成時,完成。 
 執行完所有提交任務後進行後面的操作,無返回值
static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)   返回一個新的CompletableFuture,當任何一個給定的CompletableFutures完成時,完成相同的結果。用於有返回值的,當任一執行完立即返回結果
 CompletableFuture<Object> completableFuture5 = CompletableFuture.supplyAsync(()-> {
            return "hello completableFuture5";
        });
        CompletableFuture<Object> completableFuture6 = CompletableFuture.supplyAsync(()-> {
            return "hello completableFuture6";
        },Executors.newSingleThreadExecutor());

        // allOf 若後面沒有加join(),那麼void1和void2將非同步執行,這裡不會阻塞,也就拿不到執行結果
        CompletableFuture.allOf(completableFuture5,completableFuture6)
                .thenRun(()->{
                    System.out.println("hello allof");
                }).join();

        List<CompletableFuture> completableFutureList = new ArrayList<>();
        completableFutureList.add(completableFuture5);
        completableFutureList.add(completableFuture6);
         // 方式一
        // completableFuture5 和 completableFuture6都執行完成後,輸出對應的結果
        CompletableFuture<Void> res = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()]));

        CompletableFuture<List<Object>> result = res.thenApply(v ->{
             return  completableFutureList.stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList());
                }
        );
         System.out.println(result.get());
        // 方式二
        List<Object> result2 = Stream.of(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()]))
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        System.out.println(result2);

        // completableFuture5 和 completableFuture6 隨機的,只要某個執行完成就會結束並返回結果。
        CompletableFuture<Object> anyof = CompletableFuture.anyOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()]));
        System.out.println(anyof.get());

2.3 CompletableFuture 異常處理

CompletableFuture在執行時如果遇到異常,可以使用get()並丟擲異常進行處理,但這並不是一個最好的方法。CompletableFuture本身也提供了幾種方式來處理異常

方法 描述

exceptionally(Function<Throwable,? extends T> fn)

只有當CompletableFuture丟擲異常的時候,才會觸發這個exceptionally的計算,呼叫function計算值。
 CompletableFuture<String> completableFuture7 = CompletableFuture.supplyAsync(()-> {
            int m = 1/0;
            return "hello completableFuture7";
        }).exceptionally(ex->{
            return ex.getMessage();
        });
        System.out.println(completableFuture7.get());