从CompletableFuture投掷例外 [英] Throwing exception from CompletableFuture

查看:142
本文介绍了从CompletableFuture投掷例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

// How to throw the ServerException?
public void myFunc() throws ServerException{
    // Some code
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try {
            return someObj.someFunc();
        } catch(ServerException ex) {
            // throw ex; gives an error here.
        }
    }));
    // Some code
}

someFunc ) throws a ServerException 。我不想在这里处理,但是将 someFunc()的异常从$ code> myFunc()的调用者抛出。

someFunc() throws a ServerException. I don't want to handle this here but throw the exception from someFunc() to caller of myFunc().

推荐答案

您的代码建议您在同一方法中稍后使用异步操作的结果,因此您必须处理 CompletionException ,所以处理它的一种方法是

Your code suggests that you are using the result of the asynchronous operation later in the same method, so you’ll have to deal with CompletionException anyway, so one way to deal with it, is

public void myFunc() throws ServerException {
    // Some code
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try { return someObj.someFunc(); }
        catch(ServerException ex) { throw new CompletionException(ex); }
    });
    // Some code running in parallel to someFunc()

    A resultOfA;
    try {
        resultOfA = a.join();
    }
    catch(CompletionException ex) {
        try {
            throw ex.getCause();
        }
        catch(Error|RuntimeException|ServerException possible) {
            throw possible;
        }
        catch(Throwable impossible) {
            throw new AssertionError(impossible);
        }
    }
    // some code using resultOfA
}

供应商的异步处理中抛出的所有异常将被调用到$ code> CompletionException 当调用 join ,除了 ServerException ,我们已经包装了一个 CompletionException

All exceptions thrown inside the asynchronous processing of the Supplier will get wrapped into a CompletionException when calling join, except the ServerException we have already wrapped in a CompletionException.

当我们重新抛出 CompletionException 的原因时,我们可能会面临未经检查的异常,即错误 RuntimeException 或我们的自定义检查异常 ServerException 。上面的代码使用多次捕获来处理它们,这将重新抛出它们。由于声明的返回类型 getCause() Throwable ,编译器要求我们处理该类型,尽管我们已经处理所有可能的类型。直接的解决方案是将这个实际上不可能的投掷包裹在一个 AssertionError 中。

When we re-throw the cause of the CompletionException, we may face unchecked exceptions, i.e. subclasses of Error or RuntimeException, or our custom checked exception ServerException. The code above handles all of them with a multi-catch which will re-throw them. Since the declared return type of getCause() is Throwable, the compiler requires us to handle that type despite we already handled all possible types. The straight-forward solution is to throw this actually impossible throwable wrapped in an AssertionError.

或者,我们可以使用我们的自定义异常的替代结果未来:

Alternatively, we could use an alternative result future for our custom exception:

public void myFunc() throws ServerException {
    // Some code
    CompletableFuture<ServerException> exception = new CompletableFuture<>();
    CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
        try { return someObj.someFunc(); }
        catch(ServerException ex) {
            exception.complete(ex);
            throw new CompletionException(ex);
        }
    });
    // Some code running in parallel to someFunc()

    A resultOfA;
    try {
        resultOfA = a.join();
    }
    catch(CompletionException ex) {
        if(exception.isDone()) throw exception.join();
        throw ex;
    }

    // some code using resultOfA
}

此解决方案将以包装形式重新抛出所有意外的抛弃物,但只会以 ServerException >例外未来。请注意,我们必须确保 a 已经完成(例如首先调用 join()),然后再查询例外未来,以避免竞争条件。

This solution will re-throw all "unexpected" throwables in their wrapped form, but only throw the custom ServerException in its original form passed via the exception future. Note that we have to ensure that a has been completed (like calling join() first), before we query the exception future, to avoid race conditions.

这篇关于从CompletableFuture投掷例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆