[英]CompletableFuture: How to apply a function to multiple CompletableFutures?
[英]Throw Exception in Function apply for CompletableFutures
我正在創建一些如下的任務(這只是為了演示正常的網絡調用):
public class RandomTask implements Function<String, String> {
private int number;
private int waitTime;
private boolean throwError;
public RandomTask(int number, int waitTime, boolean throwError) {
this.number = number;
this.waitTime = waitTime;
this.throwError = throwError;
}
@Override
public String apply(String s) {
System.out.println("Job " + number + " started");
try {
Thread.sleep(waitTime);
if (throwError) {
throw new InterruptedException("Something happened");
}
} catch (InterruptedException e) {
System.out.println("Error " + e.getLocalizedMessage());
}
return "RandomTask " + number + " finished";
}
}
然后,我有一個Chain類,其中每個作業將一些任務鏈接在一起。
static CompletableFuture<String> start(ExecutorService executorService) {
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Foo", executorService)
.thenApplyAsync(new RandomTask(3, 100, false), executorService)
.thenApplyAsync(new RandomTask(4, 100, false), executorService);
return future2;
}
然后,我按如下所示開始2條鏈:
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool));
try {
combinedFuture.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
這樣,兩個鏈條同時開始。
現在,我想在任務中引發異常,並在調用CombinedFuture.get()的地方捕獲該異常,以便我知道鏈中哪個任務失敗了。
問題是我無法適應Function,因為CompletableFutures對此有所抱怨。 我嘗試過:
@FunctionalInterface
public interface CheckedFunction<T, R> {
R apply(T t) throws InterruptedException;
}
但這是行不通的。 這是不可能的,或者我如何實現我的目標?
“這樣兩條鏈就同時開始了。”表明您對CompletableFuture
工作原理有根本的錯誤認識。
異步操作在創建時或在其先決條件可用時立即提交給執行者服務。 因此,在沒有依賴關系的supplyAsync
情況下,異步操作就在supplyAsync
調用內supplyAsync
開始。
就像CompletableFuture.allOf(job1, job2).get()
這樣的構造,都是根據兩個作業創建一個新階段並等待其完成,因此最終結果只是等待兩個作業的完成。 它不會開始工作。 他們已經在運行。 等待完成對完成過程沒有影響。
通過自定義函數類型鏈接CompletableFuture
可以允許檢查異常
public static <T,R> CompletableFuture<R> thenApplyAsync(
CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
Executor e) {
CompletableFuture<R> r = new CompletableFuture<>();
f.whenCompleteAsync((v,t) -> {
try {
if(t != null) r.completeExceptionally(t);
else r.complete(cf.apply(v));
} catch(Throwable t2) {
r.completeExceptionally(t2);
}
}, e);
return r;
}
要使用此方法,您必須嵌套它們,而不是在CompletableFuture
上鏈接調用。 例如
static CompletableFuture<String> start(ExecutorService executorService) {
CompletableFuture<String> future2 =
thenApplyAsync(thenApplyAsync(
CompletableFuture.supplyAsync(() -> "Foo", executorService),
new RandomTask(3, 100, false), executorService),
new RandomTask(4, 100, false), executorService);
return future2;
}
特定
public class RandomTask implements CheckedFunction<String, String> {
private int number, waitTime;
private boolean throwError;
public RandomTask(int number, int waitTime, boolean throwError) {
this.number = number;
this.waitTime = waitTime;
this.throwError = throwError;
}
@Override
public String apply(String s) throws InterruptedException {
System.out.println("Job " + number + " started");
Thread.sleep(waitTime);
if (throwError) {
throw new InterruptedException("Something happened in "+number);
}
return "RandomTask " + number + " finished";
}
}
您仍然可以創建兩個任務並等待兩個任務,例如
CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
.join();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.