给出以下代码:
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(使用前将#替换为@)