日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CompletableFuture的正常,异常,timeout和cancel

發布時間:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CompletableFuture的正常,异常,timeout和cancel 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

Java 8的CompletableFuture提供了強大的task管理能力,比如通知機制,以及更加簡單抽象的task管理。

本文中,將用CompletableFuture的 supplyAsync() 方法來創建一個異步task,task會完成特定的工作,并且返回一個String。

下面的 handleResult() 方法作為task完成時的回調函數(注意:task完成并不意味著task的實際工作一定已經運行結束了,比如timeout和cancel場景)。

public static void handleResult(String result) {System.out.println("==========result: " + result + "===========");}

一般來說,task的完成,有以下幾種原因:

  • 正常結束
  • 異常結束
  • timeout
  • cancel

本文將以代碼示例,如何處理task的不同完成狀態。

注:本文中使用的有些方法(比如 completeOnTimeout() ),是Java 9提供的。

單獨流程

正常流程

使用 thenAccept() 方法來處理task結果,代碼如下:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "hello");future.thenAccept(e -> handleResult(e));try {Thread.sleep(10* 1000);} catch (InterruptedException e) {e.printStackTrace();}

注:在主線程里面sleep一段時間,其目的是確保task在主線程結束前完成工作。

運行結果如下:

==========result: hello===========Process finished with exit code 0

異常流程

使用 exceptionally() 方法來處理task的異常,代碼如下:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {throw new RuntimeException("xxx");});// future.thenAccept(e -> handleResult(e)); // will not take effectfuture.exceptionally(e -> {System.out.println("got exception: " + e.getClass() + ", " + e.getCause());handleResult("default exception result");return "default exception result";});try {Thread.sleep(10* 1000);} catch (InterruptedException e) {e.printStackTrace();}

運行結果如下:

got exception: class java.util.concurrent.CompletionException, java.lang.RuntimeException: xxx ==========result: default exception result===========

正常和異常流程合并處理

使用 handle() 方法,它有2個參數:task結果和task異常,代碼如下:

future.handle((r, e) -> {if (e != null) {System.out.println("got exception: " + e.getClass() + ", " + e.getCause());handleResult("default exception result");return "default exception result";} else {handleResult(r);return r;}});

timeout流程

使用 completeOnTimeout() 方法,設置timeout時間,并且在timeout發生時指定task結果。代碼如下:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(5 * 1000);} catch (InterruptedException e) {e.printStackTrace();}return "hello";});future.completeOnTimeout("default timeout result", 3 * 1000, TimeUnit.MILLISECONDS);future.handle((r, e) -> {if (e != null) {System.out.println("got exception: " + e.getClass() + ", " + e.getCause());handleResult("default exception result");return "default exception result";} else {handleResult(r);return r;}});try {Thread.sleep(10* 1000);} catch (InterruptedException e) {e.printStackTrace();}

運行結果如下:

==========result: default timeout result===========

注意:在 handle() 方法里走的是正常流程,而不是異常流程。

注:也可以用 orTimeout() 方法,指定timeout時間,則在timeout發生時,task會拋出 TimeoutException 異常。

注意:timeout并不會真正停止task的運行,也不會給task發interrupt信號。

cancel流程

使用 cancel() 方法來cancel task,并拋出 CancellationException 異常。代碼如下:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(5 * 1000);} catch (InterruptedException e) {e.printStackTrace();}return "hello";});future.handle((r, e) -> {if (e != null) {System.out.println("got exception: " + e.getClass() + ", " + e.getCause());handleResult("default exception result");return "default exception result";} else {handleResult(r);return r;}});try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}future.cancel(true);try {Thread.sleep(10* 1000);} catch (InterruptedException e) {e.printStackTrace();}

運行結果如下:

got exception: class java.util.concurrent.CancellationException, null ==========result: default exception result===========

注意:cancel操作的觸發時機不可知,一般是在類之外被觸發的,所以本例中把cancel操作放在了最后(前面都是對future的基本操作)。

注意:cancel時,在 handle() 方法里走的是異常流程,其Exception為 CancellationException 。

注意:timeout并不會真正停止task的運行,也不會給task發interrupt信號。

合并流程

現在,考慮所有4種情況,把邏輯處理合到一起,代碼如下:

package com.example.test0721;import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit;public class Test0724 {public static void handleResult(String result) {System.out.println("============result: " + result + "=============");}public static void main(String[] args) {Logger log = LoggerFactory.getLogger(Test0724.class);log.info("main: started");CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {log.info("async: started");try {Thread.sleep(10 * 1000);} catch (InterruptedException e) {log.info("async: interrupted");return "default interrupted result";}boolean exceptional = false;if (exceptional) {log.info("async: run into exception");throw new RuntimeException("async exception");} else {log.info("async: finished");return "hello";}}).completeOnTimeout("default timeout result", 100 * 1000, TimeUnit.MILLISECONDS);// attention: split the line, because the cancel operation is against the above "future"future.handle((result, throwable) -> {log.info("async: result: " + result + ", throwable: " + throwable);if (throwable != null) {log.info("async: got exception from async: " + throwable.getClass() + ", " + throwable.getCause());handleResult("default exception result");return "default exception result";} else {log.info("got normal result: " + result);handleResult(result);return result;}});// try { // Thread.sleep(2 * 1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // // log.info("default cancel value"); // future.cancel(true); // log.info("main: async cancelled");try {Thread.sleep(15 * 1000);} catch (InterruptedException e) {e.printStackTrace();}log.info("main ended");} }

正常流程

直接運行代碼,就是正常流程,運行結果如下:

02:33:39.239 [main] INFO com.example.test0721.Test0724 - main: started 02:33:39.259 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: started 02:33:49.265 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: finished 02:33:49.298 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: result: hello, throwable: null 02:33:49.299 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - got normal result: hello ============result: hello============= 02:33:54.268 [main] INFO com.example.test0721.Test0724 - main ended

異常流程

把 exceptional 變量設置為 true :

boolean exceptional = true;

運行結果如下:

02:34:23.351 [main] INFO com.example.test0721.Test0724 - main: started 02:34:23.368 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: started 02:34:33.371 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: run into exception 02:34:33.410 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: result: null, throwable: java.util.concurrent.CompletionException: java.lang.RuntimeException: async exception 02:34:33.411 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: got exception from async: class java.util.concurrent.CompletionException, java.lang.RuntimeException: async exception ============result: default exception result============= 02:34:38.373 [main] INFO com.example.test0721.Test0724 - main ended

timeout流程

把task的timeout時間設置為5秒鐘:

Thread.sleep(5 * 1000);

運行結果如下:

02:35:27.985 [main] INFO com.example.test0721.Test0724 - main: started 02:35:27.996 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: started 02:35:33.040 [CompletableFutureDelayScheduler] INFO com.example.test0721.Test0724 - async: result: default timeout result, throwable: null 02:35:33.042 [CompletableFutureDelayScheduler] INFO com.example.test0721.Test0724 - got normal result: default timeout result ============result: default timeout result============= 02:35:37.999 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: run into exception 02:35:43.007 [main] INFO com.example.test0721.Test0724 - main ended

注意:timeout并不會真正停止task的運行,也不會給task發interrupt信號。本例中,由于把 exception 設置為 true ,可以看到console有 async: run into exception 的輸出。同理,假設task沒有拋異常,則最終將會在console顯示 async: finished 。

cancel流程

把下面的代碼反注釋:

try {Thread.sleep(2 * 1000);} catch (InterruptedException e) {e.printStackTrace();}log.info("default cancel value");future.cancel(true);log.info("main: async cancelled");handleResult("default cancel value");

即:在task運行到2秒鐘的時候,cancel task。運行結果如下:

02:41:03.815 [main] INFO com.example.test0721.Test0724 - main: started 02:41:03.841 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: started 02:41:05.841 [main] INFO com.example.test0721.Test0724 - default cancel value 02:41:05.870 [main] INFO com.example.test0721.Test0724 - async: result: null, throwable: java.util.concurrent.CancellationException 02:41:05.871 [main] INFO com.example.test0721.Test0724 - async: got exception from async: class java.util.concurrent.CancellationException, null ============result: default exception result============= 02:41:05.875 [main] INFO com.example.test0721.Test0724 - main: async cancelled 02:41:13.842 [ForkJoinPool.commonPool-worker-3] INFO com.example.test0721.Test0724 - async: run into exception 02:41:20.876 [main] INFO com.example.test0721.Test0724 - main ended

注意:cancel并不會真正停止task的運行,也不會給task發interrupt信號。本例中,由于把 exception 設置為 true ,可以看到console有 async: run into exception 的輸出。同理,假設task沒有拋異常,則最終將會在console顯示 async: finished 。

注意:本例中沒有區分task自身的異常和cancel task造成的異常。若想取分的話,只需在 handle() 方法里對異常加以判斷。timeout異常也同理。

總結

以上是生活随笔為你收集整理的CompletableFuture的正常,异常,timeout和cancel的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。