簡體   English   中英

函數中的拋出異常適用於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM