日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
什么,你還不會用CompletableFuture?

上一篇我們講了Future機制,有興趣的可以參考談?wù)凢uture、Callable、FutureTask關(guān)系

成都創(chuàng)新互聯(lián)公司專注于普洱網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供普洱營銷型網(wǎng)站建設(shè),普洱網(wǎng)站制作、普洱網(wǎng)頁設(shè)計、普洱網(wǎng)站官網(wǎng)定制、微信平臺小程序開發(fā)服務(wù),打造普洱網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供普洱網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

但Future機制,還不那么靈活,比如怎么去利用Future機制描述兩個任務(wù)串行執(zhí)行,又或是兩個任務(wù)并行執(zhí)行,又或是只關(guān)心最先執(zhí)行結(jié)束的任務(wù)結(jié)果。

Future機制在一定程度上都無法快速地滿足以上需求,CompletableFuture便應(yīng)運而生了。

本片會介紹CompletableFuture的api,并用一些示例演示如何去使用。

1. 創(chuàng)建一個異步任務(wù)

 
 
 
 
  1. public static  CompletableFuture supplyAsync(Supplier supplier) 
  2.  
  3.  public static  CompletableFuture supplyAsync(Supplier supplier,Executor executor); 
  4.  
  5.  public static CompletableFuture runAsync(Runnable runnable); 
  6.  
  7.  public static CompletableFuture runAsync(Runnable runnable,Executor executor); 

supplyAsync與runAsync的區(qū)別在于:supplyAsync有返回值,而runAsync沒有返回值

帶Executor參數(shù)的構(gòu)造函數(shù),則使用線程池中的線程執(zhí)行異步任務(wù)(線程池可以參考說說線程池)

不帶Executor參數(shù)的構(gòu)造函數(shù),則使用ForkJoinPool.commonPool()中的線程執(zhí)行異步任務(wù)(Fork/Join框架可以參考談?wù)劜⑿辛鱬arallelStream)

1.1 示例:使用supplyAsync創(chuàng)建一個有返回值的異步任務(wù)

 
 
 
 
  1. public class Case1 { 
  2.  
  3.     public static void main(String[] args) throws Exception { 
  4.  
  5.         CompletableFuture completableFuture=CompletableFuture.supplyAsync(()->{ 
  6.             try { 
  7.                 Thread.sleep(1000); 
  8.             } catch (InterruptedException e) { 
  9.                 e.printStackTrace(); 
  10.             } 
  11.             return 1; 
  12.         }); 
  13.         //該方法會一直阻塞 
  14.         Integer result = completableFuture.get(); 
  15.         System.out.println(result); 
  16.     } 
  17.  

2. 異步任務(wù)的回調(diào)

 
 
 
 
  1. public CompletableFuture whenComplete(BiConsumer action); 
  2.  
  3.   public CompletableFuture whenCompleteAsync(BiConsumer action); 
  4.  
  5.   public CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor); 
  6.  
  7.   public CompletableFuture exceptionally(Function fn); 

whenComplete開頭的方法在計算任務(wù)完成(包括正常完成與出現(xiàn)異常)之后會回調(diào)

而exceptionally則只會在計算任務(wù)出現(xiàn)異常時才會被回調(diào)

如何確定哪個線程去回調(diào)whenComplete,比較復(fù)雜,先略過。

而回調(diào)whenCompleteAsync的線程比較簡單,隨便拿一個空閑的線程即可,后綴是Async的方法同理。

2.1 示例:計算出現(xiàn)異常,使用whenComplete與exceptionally進行處理

 
 
 
 
  1. package com.qcy.testCompleteableFuture; 
  2.  
  3. import java.util.concurrent.CompletableFuture; 
  4. import java.util.concurrent.ExecutionException; 
  5. import java.util.function.BiConsumer; 
  6. import java.util.function.Function; 
  7. import java.util.stream.IntStream; 
  8.  
  9. /** 
  10.  * @author qcy 
  11.  * @create 2020/09/07 17:40:44 
  12.  */ 
  13. public class Case2 { 
  14.  
  15.     public static void main(String[] args) throws Exception { 
  16.  
  17.         CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { 
  18.             try { 
  19.                 Thread.sleep(1000); 
  20.             } catch (InterruptedException e) { 
  21.                 e.printStackTrace(); 
  22.             } 
  23.             System.out.println("執(zhí)行supplyAsync的線程:" + Thread.currentThread().getName()); 
  24.             int i = 1 / 0; 
  25.             return 1; 
  26.         }); 
  27.  
  28.         completableFuture.whenComplete(new BiConsumer() { 
  29.             @Override 
  30.             public void accept(Integer integer, Throwable throwable) { 
  31.                 System.out.println("執(zhí)行whenComplete的線程:" + Thread.currentThread().getName()); 
  32.                 if (throwable == null) { 
  33.                     System.out.println("計算未出現(xiàn)異常,結(jié)果:" + integer); 
  34.                 } 
  35.             } 
  36.         }); 
  37.  
  38.         completableFuture.exceptionally(new Function() { 
  39.             @Override 
  40.             public Integer apply(Throwable throwable) { 
  41.                 //出現(xiàn)異常時,則返回一個默認值 
  42.                 System.out.println("計算出現(xiàn)異常,信息:" + throwable.getMessage()); 
  43.                 return -1; 
  44.             } 
  45.         }); 
  46.  
  47.         System.out.println(completableFuture.get()); 
  48.     } 
  49.  

輸出:

當然,CompletableFuture內(nèi)的各種方法是支持鏈式調(diào)用與Lambda表達式的,我們進行如下改寫:

 
 
 
 
  1. public static void main(String[] args) throws Exception { 
  2.  
  3.      CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { 
  4.          try { 
  5.              Thread.sleep(2000); 
  6.          } catch (InterruptedException e) { 
  7.              e.printStackTrace(); 
  8.          } 
  9.          System.out.println("執(zhí)行supplyAsync的線程:" + Thread.currentThread().getName()); 
  10.          int i = 1 / 0; 
  11.          return 1; 
  12.      }).whenComplete((integer, throwable) -> { 
  13.          System.out.println("執(zhí)行whenComplete的線程:" + Thread.currentThread().getName()); 
  14.          if (throwable == null) { 
  15.              System.out.println("計算未出現(xiàn)異常,結(jié)果:" + integer); 
  16.          } 
  17.      }).exceptionally(throwable -> { 
  18.          //出現(xiàn)異常時,則返回一個默認值 
  19.          System.out.println("計算出現(xiàn)異常,信息:" + throwable.getMessage()); 
  20.          return -1; 
  21.      }); 
  22.  
  23.      System.out.println("計算結(jié)果:" + completableFuture.get()); 
  24.  } 

3. 任務(wù)串行化執(zhí)行

 
 
 
 
  1. public  CompletableFuture thenApply(Function fn); 
  2.  
  3.   public CompletableFuture thenRun(Runnable action); 
  4.  
  5.   public CompletableFuture thenAccept(Consumer action); 
  6.  
  7.   public  CompletableFuture handle(BiFunction fn); 
  8.  
  9.   public  CompletableFuture thenCompose(Function> fn); 

thenApply,依賴上一次任務(wù)執(zhí)行的結(jié)果,參數(shù)中的Function,T代表上一次任務(wù)返回值的類型,U代表當前任務(wù)返回值的類型,當上一個任務(wù)沒有出現(xiàn)異常時,thenApply才會被調(diào)用

thenRun,不需要知道上一個任務(wù)的返回結(jié)果,只是在上一個任務(wù)執(zhí)行完成之后開始執(zhí)行Runnable

thenAccept,依賴上一次任務(wù)的執(zhí)行結(jié)果,因為入?yún)⑹荂onsumer,所以不返回任何值。

handle和thenApply相似,不過當上一個任務(wù)出現(xiàn)異常時,能夠執(zhí)行handle,卻不會去執(zhí)行thenApply

thenCompose,傳入一次任務(wù)執(zhí)行的結(jié)果,返回一個新的CompleteableFuture對象

3.1 示例:使用串行化任務(wù)分解兩數(shù)相乘并輸出

 
 
 
 
  1. package com.qcy.testCompleteableFuture; 
  2.  
  3. import java.util.concurrent.CompletableFuture; 
  4.  
  5. /** 
  6.  * @author qcy 
  7.  * @create 2020/09/07 17:40:44 
  8.  */ 
  9. public class Case4 { 
  10.  
  11.     public static void main(String[] args) { 
  12.          
  13.         CompletableFuture.supplyAsync(() -> 2) 
  14.                 .thenApply(num -> num * 3) 
  15.                 .thenAccept(System.out::print); 
  16.     } 
  17.  

很顯然,輸出為6

3.2 示例:使用串行化任務(wù)并且模擬出現(xiàn)異常

 
 
 
 
  1. package com.qcy.testCompleteableFuture; 
  2.  
  3. import java.util.concurrent.CompletableFuture; 
  4. import java.util.function.BiFunction; 
  5.  
  6. /** 
  7.  * @author qcy 
  8.  * @create 2020/09/07 17:40:44 
  9.  */ 
  10. public class Case4 { 
  11.  
  12.     public static void main(String[] args) { 
  13.  
  14.         CompletableFuture.supplyAsync(() -> 2) 
  15.                 .thenApply(num -> num / 0) 
  16.                 .thenApply(result -> result * 3) 
  17.                 .handle((integer, throwable) -> { 
  18.                     if (throwable == null) { 
  19.                         return integer; 
  20.                     } else { 
  21.                         throwable.printStackTrace(); 
  22.                         return -1; 
  23.                     } 
  24.                 }).thenAccept(System.out::print); 
  25.     } 
  26.  

最終會輸出-1

4. 任務(wù)同時執(zhí)行,且都需要執(zhí)行完成

 
 
 
 
  1. public  CompletableFuture thenCombine(CompletionStage other, 
  2. Function fn); 
  3.  
  4.   public  CompletableFuture thenAcceptBoth(CompletionStage other, 
  5. Consumer action); 
  6.  
  7.   public CompletableFuture runAfterBoth(CompletionStage other,Runnable action); 
  8.  
  9.   public static CompletableFuture allOf(CompletableFuture... cfs); 

thenCombine,合并兩個任務(wù),兩個任務(wù)可以同時執(zhí)行,都執(zhí)行成功后,執(zhí)行最后的BiFunction操作。其中T代表第一個任務(wù)的執(zhí)行結(jié)果類型,U代表第二個任務(wù)的執(zhí)行結(jié)果類型,V代表合并的結(jié)果類型

thenAcceptBoth,和thenCombine特性用法都極其相似,唯一的區(qū)別在于thenAcceptBoth進行一個消費,沒有返回值

runAfterBoth,兩個任務(wù)都執(zhí)行完成后,但不關(guān)心他們的返回結(jié)構(gòu),然后去執(zhí)行一個Runnable。

allOf,當所有的任務(wù)都執(zhí)行完成后,返回一個CompletableFuture

4.1 示例:使用thenCombine合并任務(wù)

 
 
 
 
  1. package com.qcy.testCompleteableFuture; 
  2.  
  3. import java.util.concurrent.CompletableFuture; 
  4. import java.util.concurrent.ExecutionException; 
  5.  
  6. /** 
  7.  * @author qcy 
  8.  * @create 2020/09/07 17:40:44 
  9.  */ 
  10. public class Case5 { 
  11.  
  12.     public static void main(String[] args) throws Exception { 
  13.  
  14.         CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> { 
  15.             System.out.println("任務(wù)1開始"); 
  16.             try { 
  17.                 Thread.sleep(3000); 
  18.             } catch (InterruptedException e) { 
  19.                 e.printStackTrace(); 
  20.             } 
  21.             System.out.println("任務(wù)1結(jié)束"); 
  22.             return 2; 
  23.         }); 
  24.  
  25.         CompletableFuture cf2 = CompletableFuture.supplyAsync(() -> { 
  26.             System.out.println("任務(wù)2開始"); 
  27.             try { 
  28.                 Thread.sleep(3000); 
  29.             } catch (InterruptedException e) { 
  30.                 e.printStackTrace(); 
  31.             } 
  32.             System.out.println("任務(wù)2結(jié)束"); 
  33.             return 3; 
  34.         }); 
  35.  
  36.         CompletableFuture completableFuture = cf1.thenCombine(cf2, (result1, result2) -> result1 * result2); 
  37.         System.out.println("計算結(jié)果:" + completableFuture.get()); 
  38.     } 
  39.  

輸出:

可以看到兩個任務(wù)確實是同時執(zhí)行的

當然,熟練了之后,直接使用鏈式操作,代碼如下:

 
 
 
 
  1. package com.qcy.testCompleteableFuture; 
  2.  
  3. import java.util.concurrent.CompletableFuture; 
  4.  
  5. /** 
  6.  * @author qcy 
  7.  * @create 2020/09/07 17:40:44 
  8.  */ 
  9. public class Case6 { 
  10.  
  11.     public static void main(String[] args) throws Exception { 
  12.  
  13.         CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { 
  14.             System.out.println("任務(wù)1開始"); 
  15.             try { 
  16.                 Thread.sleep(3000); 
  17.             } catch (InterruptedException e) { 
  18.                 e.printStackTrace(); 
  19.             } 
  20.             System.out.println("任務(wù)1結(jié)束"); 
  21.             return 2; 
  22.         }).thenCombine(CompletableFuture.supplyAsync(() -> { 
  23.             System.out.println("任務(wù)2開始"); 
  24.             try { 
  25.                 Thread.sleep(2000); 
  26.             } catch (InterruptedException e) { 
  27.                 e.printStackTrace(); 
  28.             } 
  29.             System.out.println("任務(wù)2結(jié)束"); 
  30.             return 3; 
  31.         }), (result1, result2) -> result1 * result2); 
  32.  
  33.         System.out.println("計算結(jié)果:" + completableFuture.get()); 
  34.     } 
  35.  

5. 任務(wù)同時執(zhí)行,且只取最先完成的那個任務(wù)

 
 
 
 
  1. public  CompletableFuture applyToEither(CompletionStage other, Function fn); 
  2.  
  3.    public CompletableFuture acceptEither(CompletionStage other, Consumer action); 
  4.  
  5.    public CompletableFuture runAfterEither(CompletionStage other,Runnable action); 
  6.  
  7.    public static CompletableFuture anyOf(CompletableFuture... cfs); 

    applyToEither,最新執(zhí)行完任務(wù),將其結(jié)果執(zhí)行Function操作,其中T是最先執(zhí)行完的任務(wù)結(jié)果類型,U是最后輸出的類型

    acceptEither,最新執(zhí)行完的任務(wù),將其結(jié)果執(zhí)行消費操作

    runAfterEither,任意一個任務(wù)執(zhí)行完成之后,執(zhí)行Runnable操作

    anyOf,多個任務(wù)中,返回最先執(zhí)行完成的CompletableFuture

    5.1 示例:兩個任務(wù)同時執(zhí)行,打印最先完成的任務(wù)的結(jié)果

     
     
     
     
    1. package com.qcy.testCompleteableFuture; 
    2.  
    3. import java.util.concurrent.CompletableFuture; 
    4.  
    5. /** 
    6.  * @author qcy 
    7.  * @create 2020/09/07 17:40:44 
    8.  */ 
    9. public class Case7 { 
    10.  
    11.     public static void main(String[] args) throws Exception { 
    12.  
    13.         CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { 
    14.             System.out.println("任務(wù)1開始"); 
    15.             try { 
    16.                 Thread.sleep(3000); 
    17.             } catch (InterruptedException e) { 
    18.                 e.printStackTrace(); 
    19.             } 
    20.             System.out.println("任務(wù)1結(jié)束"); 
    21.             return 2; 
    22.         }).acceptEither(CompletableFuture.supplyAsync(() -> { 
    23.             System.out.println("任務(wù)2開始"); 
    24.             try { 
    25.                 Thread.sleep(2000); 
    26.             } catch (InterruptedException e) { 
    27.                 e.printStackTrace(); 
    28.             } 
    29.             System.out.println("任務(wù)2結(jié)束"); 
    30.             return 3; 
    31.         }), result -> System.out.println(result)); 
    32.  
    33.         //等待CompletableFuture返回,防止主線程退出 
    34.         completableFuture.join(); 
    35.     } 
    36.  

    輸出:

    可以看得到,任務(wù)2結(jié)束后,直接不再執(zhí)行任務(wù)1的剩余代碼

    5.2 示例:多個任務(wù)同時執(zhí)行,打印最先完成的任務(wù)的結(jié)果

     
     
     
     
    1. package com.qcy.testCompleteableFuture; 
    2.  
    3. import java.util.concurrent.CompletableFuture; 
    4.  
    5. /** 
    6.  * @author qcy 
    7.  * @create 2020/09/07 17:40:44 
    8.  */ 
    9. public class Case8 { 
    10.  
    11.     public static void main(String[] args) throws Exception { 
    12.  
    13.         CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> { 
    14.             System.out.println("任務(wù)1開始"); 
    15.             try { 
    16.                 Thread.sleep(3000); 
    17.             } catch (InterruptedException e) { 
    18.                 e.printStackTrace(); 
    19.             } 
    20.             System.out.println("任務(wù)1結(jié)束"); 
    21.             return 2; 
    22.         }); 
    23.  
    24.         CompletableFuture cf2 = CompletableFuture.supplyAsync(() -> { 
    25.             System.out.println("任務(wù)2開始"); 
    26.             try { 
    27.                 Thread.sleep(2000); 
    28.             } catch (InterruptedException e) { 
    29.                 e.printStackTrace(); 
    30.             } 
    31.             System.out.println("任務(wù)2結(jié)束"); 
    32.             return 3; 
    33.         }); 
    34.  
    35.         CompletableFuture cf3 = CompletableFuture.supplyAsync(() -> { 
    36.             System.out.println("任務(wù)3開始"); 
    37.             try { 
    38.                 Thread.sleep(4000); 
    39.             } catch (InterruptedException e) { 
    40.                 e.printStackTrace(); 
    41.             } 
    42.             System.out.println("任務(wù)3結(jié)束"); 
    43.             return 4; 
    44.         }); 
    45.  
    46.         CompletableFuture firstCf = CompletableFuture.anyOf(cf1, cf2, cf3); 
    47.         System.out.println(firstCf.get()); 
    48.     } 
    49.  
    50. 輸出:


      當前題目:什么,你還不會用CompletableFuture?
      分享網(wǎng)址:http://www.5511xx.com/article/dghhihg.html