异常导致 Future 永远不会完成 [英] Exception causes Future to never complete

查看:60
本文介绍了异常导致 Future 永远不会完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下代码:

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.

The future f never completes. f.value is always None.

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

There was a known bug in scala-2.10 that was fixed:

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

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

我使用的是 Scala-2.11.

I am on scala-2.11.

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

The example from the bug report uses NotImplementedErorr, which is correctly handled by the Future and it will complete. However, if I use InternalError as in my example above, then the Future never completes. This is true whether I use the ExecutionContext.global, Executors.newSingleThreadExecutor, or Executors.newFixedThreadPool.

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

I can catch Throwable in the body of the Future and re-throw it with an exception wrapped around it that I know the Future will handle correctly, but that's a terrible solution.

这是一个已知问题吗?预期行为?我有哪些选择可以让我的期货行为保持理智?

Is this a known issue? Expected behavior? What options do I have to get sane behavior out of my Futures?

推荐答案

来自未来.

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

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

As you can see, Future is only catching NonFatal exception.

下面是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,正在运行任务的线程只是被异常杀死,承诺永远不会完成.

Since java.lang.InternalError is subclass of VirtualMachineError, the thread which is running the task is just killed by exception, and the promise will never be completed.

来自未来例外情况的概述

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

Fatal exceptions (as determined by NonFatal) are rethrown in the thread executing the failed asynchronous computation. This informs the code managing the executing threads of the problem and allows it to fail fast, if necessary. See NonFatal for a more precise description of the semantics.

因此,我认为这是有意为之.

Therefore I think this is intended behavior.

这篇关于异常导致 Future 永远不会完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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