异常导致 Future 永远无法完成

2024-04-06

给出以下代码:

import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors

val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))

val f = Future[Unit](throw new java.lang.InternalError())(ec)

未来f永远不会完成。f.value总是None.

scala-2.10 中有一个已知错误已修复:

http://mandubian.com/2013/02/22/scala-future-fatal-exception http://mandubian.com/2013/02/22/scala-future-fatal-exception

https://issues.scala-lang.org/browse/SI-7029 https://issues.scala-lang.org/browse/SI-7029

我使用的是 scala-2.11。

错误报告中的示例使用 NotImplementedErorr,它由 Future 正确处理并且将会完成。但是,如果我像上面的示例一样使用 InternalError,那么 Future 永远不会完成。无论我使用 ExecutionContext.global、Executors.newSingleThreadExecutor 还是 Executors.newFixedThreadPool,都是如此。

我可以在 Future 的主体中捕获 Throwable 并重新抛出它,并在其周围包含一个异常,我知道 Future 会正确处理该异常,但这是一个糟糕的解决方案。

这是一个已知的问题?预期的行为?我必须采取哪些选择才能让我的 Future 保持理智的行为?


从源头来说Future https://github.com/scala/scala/blob/v2.11.7/src/library/scala/concurrent/impl/Future.scala.

override def run() = {
  promise complete {
    try Success(body) catch { case NonFatal(e) => Failure(e) }
  }
}

如你看到的,Future只是捕捉NonFatal例外。

而下面的内容就是NonFatal https://github.com/scala/scala/blob/v2.11.7/src/library/scala/util/control/NonFatal.scala火柴。

def apply(t: Throwable): Boolean = t match {
  // VirtualMachineError includes OutOfMemoryError and other fatal errors
  case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
  case _ => true

}

Since java.lang.InternalError https://docs.oracle.com/javase/8/docs/api/java/lang/InternalError.html是的子类VirtualMachineError,正在运行任务的线程只是被异常杀死,并且承诺将永远不会完成。

从概述来看未来的例外情况 http://docs.scala-lang.org/overviews/core/futures.html#exceptions

致命异常(由 NonFatal 确定)将在执行失败的异步计算的线程中重新引发。这会通知管理问题执行线程的代码,并允许其在必要时快速失败。有关语义的更精确描述,请参阅 NonFatal。

因此我认为这是有意的行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

异常导致 Future 永远无法完成 的相关文章

随机推荐