【问题标题】:Exception causes Future to never complete异常导致 Future 永远无法完成
【发布时间】:2015-12-14 23:31:14
【问题描述】:

给定以下代码:

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

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

我正在使用 scala-2.11。

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

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

这是一个已知问题吗?预期的行为?我有哪些选择可以让我的 Futures 行为正常?

【问题讨论】:

  • 我找不到任何关于这是故意的文档,但这种行为似乎只发生在 Throwable 子类型本身不是 Exception 的子类型

标签: scala


【解决方案1】:

来自Future的来源。

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

如您所见,Future 仅捕获 NonFatal 异常。

以下是NonFatal 匹配的内容。

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

}

由于java.lang.InternalErrorVirtualMachineError 的子类,所以运行任务的线程只是被异常杀死,promise 永远不会完成。

来自exceptions in the future的概述

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

因此我认为这是预期的行为。

【讨论】:

  • 是的,在线程中重新抛出异常显然是有意的行为,但这似乎是一种疏忽,导致 Future 永远不会完成。用户需要确保任何等待 Future 的东西都能通过其他机制得到失败通知。
  • @pheaver 我认为在发生致命错误时不应该通知Future。这应该是执行者的工作。但是,对于当前Future 的行为groups.google.com/forum/#!topic/scala-internals/45ianF2rQYQ 进行了长时间的讨论。由于 StackOverflow 不是一个可以讨论的网站,我认为您应该在 scala 论坛上发布一个问题。
  • @pheaver 你也可以提供记者作为ExecutionContext.fromExecutor(null, reporter) stackoverflow.com/questions/25709602/… 的第二个参数,但似乎不适用于固定线程池
猜你喜欢
  • 2014-09-07
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多