最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java中CompletableFuture的作用是什么

這篇文章給大家介紹Java中CompletableFuture的作用是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創(chuàng)新互聯(lián)公司專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、中山網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5、商城開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為中山等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

創(chuàng)建CompletableFuture對象。

以下四個靜態(tài)方法用來為一段異步執(zhí)行的代碼創(chuàng)建CompletableFuture對象:

public static CompletableFuture              runAsync(Runnable runnable)  public static CompletableFuture              runAsync(Runnable runnable, Executor executor)  public static  CompletableFuture supplyAsync(Supplier supplier)  public static  CompletableFuture supplyAsync(Supplier supplier, Executor executor)

runAsync方法也好理解,它以Runnable函數(shù)式接口類型為參數(shù),所以CompletableFuture的計算結(jié)果為空。以Async結(jié)尾會使用其它的線程去執(zhí)行,沒有指定Executor的方法會使用ForkJoinPool.commonPool()作為它的線程池執(zhí)行異步代碼。

supplyAsync方法以Supplier函數(shù)式接口類型為參數(shù),CompletableFuture的計算結(jié)果類型為U。

因為方法的參數(shù)類型都是函數(shù)式接口,所以可以使用lambda表達式實現(xiàn)異步任務(wù),比如:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      //長時間的計算任務(wù)      return "hello world";  });

計算結(jié)果完成時的處理

當(dāng)CompletableFuture的計算結(jié)果完成,或者拋出異常的時候,我們可以執(zhí)行特定的Action。主要是下面的方法:

public CompletableFuture  whenComplete(BiConsumer action)  public CompletableFuture  whenCompleteAsync(BiConsumer action)  public CompletableFuture  whenCompleteAsync(BiConsumer action, Executor executor)  public CompletableFuture  exceptionally(Function fn)

可以看到Action的類型是BiConsumer,它可以處理正常的計算結(jié)果,或者異常情況。

注意這幾個方法都會返回CompletableFuture,當(dāng)Action執(zhí)行完畢后它的結(jié)果返回原始的CompletableFuture的計算結(jié)果或者返回異常。

public class Main {      private static Random rand = new Random();      private static long t = System.currentTimeMillis();      static int getMoreData() {          System.out.println("begin to start compute");          try {              Thread.sleep(10000);          } catch (InterruptedException e) {              throw new RuntimeException(e);          }          System.out.println("end to start compute. passed " + (System.currentTimeMillis() - t)/1000 + " seconds");          return rand.nextInt(1000);      }      public static void main(String[] args) throws Exception {          CompletableFuture future = CompletableFuture.supplyAsync(Main::getMoreData);          Future f = future.whenComplete((v, e) -> {              System.out.println(v);              System.out.println(e);          });          System.out.println(f.get());          System.in.read();      }  }

exceptionally方法返回一個新的CompletableFuture,當(dāng)原始的CompletableFuture拋出異常的時候,就會觸發(fā)這個CompletableFuture的計算,調(diào)用function計算值,否則如果原始的CompletableFuture正常計算完后,這個新的CompletableFuture也計算完成,它的值和原始的CompletableFuture的計算的值相同。也就是這個exceptionally方法用來處理異常的情況。

結(jié)果轉(zhuǎn)換

由于回調(diào)風(fēng)格的實現(xiàn),我們不必因為等待一個計算完成而阻塞著調(diào)用線程,而是告訴CompletableFuture當(dāng)計算完成的時候請執(zhí)行某個function。而且我們還可以將這些操作串聯(lián)起來,或者將CompletableFuture組合起來。

public  CompletableFuture  thenApply(Function fn)  public  CompletableFuture  thenApplyAsync(Function fn)  public  CompletableFuture  thenApplyAsync(Function fn, Executor executor)

這一組函數(shù)的功能是當(dāng)原來的CompletableFuture計算完后,將結(jié)果傳遞給函數(shù)fn,將fn的結(jié)果作為新的CompletableFuture計算結(jié)果。因此它的功能相當(dāng)于將CompletableFuture轉(zhuǎn)換成CompletableFuture。

使用例子如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture f =  future.thenApplyAsync(i -> i * 10).thenApply(i -> i.toString());  System.out.println(f.get()); //"1000"

需要注意的是,這些轉(zhuǎn)換并不是馬上執(zhí)行的,也不會阻塞,而是在前一個stage完成后繼續(xù)執(zhí)行。

下面一組方法雖然也返回CompletableFuture對象,但是對象的值和原來的CompletableFuture計算的值不同。當(dāng)原先的CompletableFuture的值計算完成或者拋出異常的時候,會觸發(fā)這個CompletableFuture對象的計算,結(jié)果由BiFunction參數(shù)計算而得。因此這組方法兼有whenComplete和轉(zhuǎn)換的兩個功能。

public  CompletableFuture     handle(BiFunction fn)  public  CompletableFuture     handleAsync(BiFunction fn)  public  CompletableFuture     handleAsync(BiFunction fn, Executor executor)

它們與thenApply* 方法的區(qū)別在于handle*方法會處理正常計算值和異常,因此它可以屏蔽異常,避免異常繼續(xù)拋出。而thenApply*方法只是用來處理正常值,因此一旦有異常就會拋出。

純消費結(jié)果

上面的方法是當(dāng)計算完成的時候,會生成新的計算結(jié)果(thenApply, handle),或者返回同樣的計算結(jié)果(whenComplete,CompletableFuture)。CompletableFuture提供了一種處理結(jié)果的方法,只對結(jié)果執(zhí)行Action,而不返回新的計算值,因此計算值為Void:

public CompletableFuture  thenAccept(Consumer action)  public CompletableFuture  thenAcceptAsync(Consumer action)  public CompletableFuture  thenAcceptAsync(Consumer action, Executor executor)

看它的參數(shù)類型也就明白了,它們是消費型函數(shù)式接口Consumer,這個接口只有輸入,沒有返回值。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture f =  future.thenAccept(System.out::println);  System.out.println(f.get());  public  CompletableFuture                thenAcceptBoth(CompletionStage other, BiConsumer action)  public  CompletableFuture                thenAcceptBothAsync(CompletionStage other, BiConsumer action)  public  CompletableFuture                thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor)  public CompletableFuture  runAfterBoth(CompletionStage other,  Runnable action)

thenAcceptBoth以及相關(guān)方法提供了類似的功能,當(dāng)兩個CompletionStage都正常完成計算的時候,就會執(zhí)行提供的action,它用來組合另外一個異步的結(jié)果。

runAfterBoth是當(dāng)兩個CompletionStage都正常完成計算的時候,執(zhí)行一個Runnable,這個Runnable并不使用計算的結(jié)果。

例子如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture f =  future.thenAcceptBoth(CompletableFuture.completedFuture(10), (x, y) -> System.out.println(x * y));  System.out.println(f.get());

更徹底地,下面一組方法當(dāng)計算完成的時候會執(zhí)行一個Runnable,與thenAccept不同,Runnable并不使用CompletableFuture計算的結(jié)果。

public CompletableFuture  thenRun(Runnable action)  public CompletableFuture  thenRunAsync(Runnable action)  public CompletableFuture  thenRunAsync(Runnable action,  Executor executor)

因此先前的CompletableFuture計算的結(jié)果被忽略了,這個方法返回CompletableFuture類型的對象。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture f =  future.thenRun(() -> System.out.println("finished"));  System.out.println(f.get());

因此,你可以根據(jù)方法的參數(shù)的類型來加速你的記憶。Runnable類型的參數(shù)會忽略計算的結(jié)果,Consumer是純消費計算結(jié)果,BiConsumer會組合另外一個CompletionStage純消費,F(xiàn)unction會對計算結(jié)果做轉(zhuǎn)換,BiFunction會組合另外一個CompletionStage的計算結(jié)果做轉(zhuǎn)換。

組合

有時,你需要在一個future結(jié)構(gòu)運行某個函數(shù),但是這個函數(shù)也是返回某種future,也就是說是兩個future彼此依賴串聯(lián)在一起,它類似于flatMap。

public  CompletableFuture  thenCompose(Function> fn)  public  CompletableFuture  thenComposeAsync(Function> fn)  public  CompletableFuture  thenComposeAsync(Function> fn,  Executor executor)

這一組方法接受一個Function作為參數(shù),這個Function的輸入是當(dāng)前的CompletableFuture的計算值,返回結(jié)果將是一個新的CompletableFuture,這個新的CompletableFuture會組合原來的CompletableFuture和函數(shù)返回的CompletableFuture。因此它的功能類似:

A +--> B +---> C

記住,thenCompose返回的對象并不一是函數(shù)fn返回的對象,如果原來的CompletableFuture還沒有計算出來,它就會生成一個新的組合后的CompletableFuture。

例子:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture f =  future.thenCompose( i -> {      return CompletableFuture.supplyAsync(() -> {          return (i * 10) + "";      });  });  System.out.println(f.get()); //1000

而下面的一組方法thenCombine用來復(fù)合另外一個CompletionStage的結(jié)果。它的功能類似:

A +

|

+------> C

+------^

B +

兩個CompletionStage是并行執(zhí)行的,它們之間并沒有先后依賴順序,other并不會等待先前的CompletableFuture執(zhí)行完畢后再執(zhí)行。

public  CompletableFuture thenCombine(CompletionStage other, BiFunction fn)  public  CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn)  public  CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor)

其實從功能上來講,它們的功能更類似thenAcceptBoth,只不過thenAcceptBoth是純消費,它的函數(shù)參數(shù)沒有返回值,而thenCombine的函數(shù)參數(shù)fn有返回值。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {      return 100;  });  CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {      return "abc";  });  CompletableFuture f =  future.thenCombine(future2, (x,y) -> y + "-" + x);  System.out.println(f.get()); //abc-100

Either

thenAcceptBoth和runAfterBoth是當(dāng)兩個CompletableFuture都計算完成,而我們下面要了解的方法是當(dāng)任意一個CompletableFuture計算完成的時候就會執(zhí)行。

public CompletableFuture        acceptEither(CompletionStage other, Consumer action)  public CompletableFuture        acceptEitherAsync(CompletionStage other, Consumer action)  public CompletableFuture        acceptEitherAsync(CompletionStage other, Consumer action, Executor executor)  public  CompletableFuture     applyToEither(CompletionStage other, Function fn)  public  CompletableFuture     applyToEitherAsync(CompletionStage other, Function fn)  public  CompletableFuture     applyToEitherAsync(CompletionStage other, Function fn, Executor executor)

acceptEither方法是當(dāng)任意一個CompletionStage完成的時候,action這個消費者就會被執(zhí)行。這個方法返回CompletableFuture

applyToEither方法是當(dāng)任意一個CompletionStage完成的時候,fn會被執(zhí)行,它的返回值會當(dāng)作新的CompletableFuture的計算結(jié)果。

下面這個例子有時會輸出100,有時候會輸出200,哪個Future先完成就會根據(jù)它的結(jié)果計算。

Random rand = new Random();  CompletableFuture future = CompletableFuture.supplyAsync(() -> {      try {          Thread.sleep(10000 + rand.nextInt(1000));      } catch (InterruptedException e) {          e.printStackTrace();      }      return 100;  });  CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {      try {          Thread.sleep(10000 + rand.nextInt(1000));      } catch (InterruptedException e) {          e.printStackTrace();      }      return 200;  });  CompletableFuture f =  future.applyToEither(future2,i -> i.toString());

輔助方法 allOf 和 anyOf

前面我們已經(jīng)介紹了幾個靜態(tài)方法:completedFuture、runAsync、supplyAsync,下面介紹的這兩個方法用來組合多個CompletableFuture。

public static CompletableFuture  allOf(CompletableFuture... cfs)  public static CompletableFuture  anyOf(CompletableFuture... cfs)

allOf方法是當(dāng)所有的CompletableFuture都執(zhí)行完后執(zhí)行計算。

anyOf方法是當(dāng)任意一個CompletableFuture執(zhí)行完后就會執(zhí)行計算,計算的結(jié)果相同。

下面的代碼運行結(jié)果有時是100,有時是"abc"。但是anyOf和applyToEither不同。anyOf接受任意多的CompletableFuture,但是applyToEither只是判斷兩個CompletableFuture。anyOf返回值的計算結(jié)果是參數(shù)中其中一個CompletableFuture的計算結(jié)果,applyToEither返回值的計算結(jié)果卻是要經(jīng)過fn處理的。當(dāng)然還有靜態(tài)方法的區(qū)別,線程池的選擇等。

Random rand = new Random();  CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {      try {          Thread.sleep(10000 + rand.nextInt(1000));      } catch (InterruptedException e) {          e.printStackTrace();      }      return 100;  });  CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {      try {          Thread.sleep(10000 + rand.nextInt(1000));      } catch (InterruptedException e) {          e.printStackTrace();      }      return "abc";  });  //CompletableFuture f =  CompletableFuture.allOf(future1,future2);  CompletableFuture f =  CompletableFuture.anyOf(future1,future2);  System.out.println(f.get());

更進一步

Guava的Future類,它的Futures輔助類提供了很多便利方法,用來處理多個Future,而不像Java的CompletableFuture,只提供了allOf、anyOf兩個方法。 比如有這樣一個需求,將多個CompletableFuture組合成一個CompletableFuture,這個組合后的CompletableFuture的計算結(jié)果是個List,它包含前面所有的CompletableFuture的計算結(jié)果,guava的Futures.allAsList可以實現(xiàn)這樣的功能,但是對于java CompletableFuture,我們需要一些輔助方法:

public static  CompletableFuture> sequence(List> futures) {         CompletableFuture allDoneFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));         return allDoneFuture.thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()));     }  public static  CompletableFuture> sequence(Stream> futures) {         List> futureList = futures.filter(f -> f != null).collect(Collectors.toList());         return sequence(futureList);     }

或者Java Future轉(zhuǎn)CompletableFuture:

 public static  CompletableFuture toCompletable(Future future, Executor executor) {     return CompletableFuture.supplyAsync(() -> {          try {              return future.get();          } catch (InterruptedException | ExecutionException e) {              throw new RuntimeException(e);          }      }, executor);  }

關(guān)于Java中CompletableFuture的作用是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


網(wǎng)頁標(biāo)題:Java中CompletableFuture的作用是什么
URL分享:http://fisionsoft.com.cn/article/geedee.html