CompletableFuture的用法及簡要原理

//自定義線程池
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(8,16,20, TimeUnit.SECONDS,new LinkedBlockingDeque<>(20), Executors.defaultThreadFactory(), (r, executor1) -> new Thread(r).start());
 System.out.println("Main 線程名稱: "+Thread.currentThread().getName());

//runAsync 開啓一個異步任務,接受一個Runnable,可選傳入自定義線程池
CompletableFuture.runAsync(()-> System.out.println(Thread.currentThread().getName()+"     CSDN——Mutou_ren  CompletableFuture.runAsync"),executor);
//supplyAsync 開啓一個異步任務,接受一個supplier函數,如果不指定自定義線程池默認都是使用ForkJoinPool.commonPool線程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()-> (Thread.currentThread().getName()+"     CSDN——Mutou_ren  CompletableFuture.supplyAsync"));
System.out.println(Thread.currentThread().getName()+"   "+future1.get());

在這裏插入圖片描述

thenRun

//thenRun接受一個runnable ,無法讀取前面的結果
 CompletableFuture.supplyAsync(()->{
            System.out.println("thenRun前置準備睡眠");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thenRun前置睡眠結束");
            return 1;
        }).thenRun(()-> System.out.println("then run 執行,無法拿到前置任務的結果"));

在這裏插入圖片描述

thenAccept

//thenAccept可以接收一個consumer,能讀取到前面的結果
 CompletableFuture.supplyAsync(()->{
            System.out.println("thenAccept前置準備睡眠");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thenAccept前置睡眠結束");
            return "thenAccept前置返回值";
        }).thenAccept(e-> System.out.println("then accept 可以收到前置任務的結果爲:"+e));

在這裏插入圖片描述

thenApply

//thenApply接收一個function,可以讀取前面的結果並返回新的結果,
 CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
            System.out.println("thenApply前置準備睡眠");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thenAccept前置睡眠結束");
            return "thenApply前置返回值";
        }).thenApply(e->e+" then apply 添加");
       System.out.println(Thread.currentThread().getName()+future2.get());

在這裏插入圖片描述

whenComplete

  CompletableFuture future3 = CompletableFuture.supplyAsync(()->{
            System.out.println("thenAccept前置準備睡眠");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thenAccept前置睡眠結束");
            return "future3";
        });
//設置回調,t代表異常thrown
future3.whenComplete((e,t)-> System.out.println(Thread.currentThread().getName()+"whenComplete "+e));

在這裏插入圖片描述

thenCombine

//收集前面的和當前的CompletableFuture 的返回值作爲參數,傳遞給function
 CompletableFuture future7 = CompletableFuture.supplyAsync(()->"then").thenCombine( CompletableFuture.supplyAsync(()->"combine"),(a,b)-> a+" "+b);
        System.out.println(future7.get());

在這裏插入圖片描述

thenCompose

//前面的CompletableFuture 返回值可以作爲下一個CompletableFuture 的參數
CompletableFuture future8 = CompletableFuture.supplyAsync(()->"then").thenCompose(str -> CompletableFuture.supplyAsync(()-> str+" compose"));
        System.out.println(future8.get());

在這裏插入圖片描述

allof

//模擬耗時操作
public static Integer getResult(int integer){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return integer;
    }
    
  List<CompletableFuture<Integer>> futureList = new ArrayList(50);
        for (int i=0;i<50;i++){
            futureList.add(CompletableFuture.supplyAsync(()->getResult(1),executor));
        }
//在另一個流上對每個future進行join操作,等價allof
List<Integer> resultList = futureList.stream().map(e -> e.join()).collect(Collectors.toList());
System.out.println(resultList.size());

在這裏插入圖片描述

//將多個future合併成一個等待
CompletableFuture all = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
//這裏返回就代表列表中所有的future全返回了
all.get();
System.out.println(futureList.stream().filter(e -> !e.isDone()).count());

在這裏插入圖片描述

anyof

 List<CompletableFuture<Integer>> futureList = new ArrayList(50);
        for (int i=0;i<50;i++){
            futureList.add(CompletableFuture.supplyAsync(()->getResult(1),executor));
        }
CompletableFuture any = CompletableFuture.anyOf(futureList.toArray(new CompletableFuture[futureList.size()]));
//這裏返回就代表列表中有future返回了
any.get();
System.out.println(futureList.stream().filter(e -> !e.isDone()).count());

在這裏插入圖片描述

原理

CompletableFuture.supplyAsync等方法中,實際上就是新建了一個CompletableFuture對象,然後使用線程池運行任務並立即將這個CompletableFuture對象返回。在線程池運行任務時,會在run後將結果通過future.complete()或異常future.completeExceptionlly()設置到CompletableFuture對象中

Future.get

調用get時會判斷任務狀態是否結束,若沒有結束則構建成等待節點並park;當任務完成進行set結果或異常set異常時,會通過finishCompletion()將所有等待的節點線程unpark並刪除節點,思想還是AQS那套思想

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章