java - 异步方法抛出异常是否合理?

标签 java multithreading asynchronous promise completable-future

在 Java 中开发一个具有 CompletableFuture 返回类型的异步方法,我们希望生成的 CF 正常或异常完成,具体取决于该方法是成功还是失败。

但是,考虑例如我的方法写入 AsynchronousChannel 并在打开该 channel 时遇到异常。它甚至还没有开始写作。所以,在这种情况下,我倾向于让异常流向调用者。对吗?

尽管调用者必须处理 2 种失败情况:1) 异常,或 2) 拒绝 promise 。

或者,我的方法是否应该捕获该异常并返回一个被拒绝的 promise ?

最佳答案

IMO,选项 1) 使 API 更难使用,因为将有两种不同的通信错误路径:

  1. “同步”异常,方法在抛出异常时结束。
  2. “异步”异常,其中方法返回一个 CF,它以异常完成。请注意,不可能避免这种情况,因为总是会出现只有在异步路径启动后才发现错误的情况(例如超时)。

程序员现在必须确保正确处理这两条路径,而不是只处理一条。

同样有趣的是,C# 和 Javascript 的行为总是通过返回的 Task 报告在 async 函数体内抛出的异常/Promise,即使是在第一个 await 之前抛出的异常,也永远不会以异常结束 async 函数调用。

对于 Kotlin 的协程也是如此,即使在使用 Unconfined 调度程序时也是如此

class SynchronousExceptionExamples {
    @Test
    fun example() {
        log.info("before launch")
        val job = GlobalScope.launch(Dispatchers.Unconfined) {
            log.info("before throw")
            throw Exception("an-error")
        }
        log.info("after launch")
        Thread.sleep(1000)
        assertTrue(job.isCancelled)
    }
}

会产生

6 [main] INFO SynchronousExceptionExamples - before launch
73 [main @coroutine#1] INFO SynchronousExceptionExamples - before throw
(...)
90 [main] INFO SynchronousExceptionExamples - after launch

请注意,异常发生在 main 线程中,但是 launch 以正确的 Job 结束。

关于java - 异步方法抛出异常是否合理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54221665/

相关文章:

java - 检测空输入(JAVA)

c# - 从 Threadpool 工作线程启动进程(并在需要时等待)

java.util.logging.Logger吞咽日志

java - JScrollpane 无法正常显示

android - 线程中的值未更新

python - 在 ctypes 回调函数中使用线程锁

python - 如何在基于 Python Klein 的 Web 服务中使用多核

vb.net - VS.Net 2008 中的 "Asynchronous Processing=true"和 Quickwatch/Watch 问题

C# async/await - 程序如何跟踪调用 "await"的位置?

java - 查询InputStream "System.in"