scala - 为什么我的Scala future 无法传播错误?

标签 scala exception error-handling future

该代码按预期工作:

it("should propagate exceptions") {
  intercept[RuntimeException] {
    val future = Future { Thread.sleep(10); sys.error("whoops"); 22 }
    Await.result(future, Duration.Inf)
  }.getMessage should equal ("whoops")
}

但这不是:
it("should propagate errors") {
  intercept[StackOverflowError] {
    val future = Future { Thread.sleep(10); throw new StackOverflowError("dang"); 22 }
    Await.result(future, Duration.Inf)
  }.getMessage should equal ("dang")
}

在第二次测试中的 future 永远不会回来。为什么Error子类(而不是Exception子类)不能终止我的 future ?我应该如何处理Error

编辑:这可能与Why does Scala Try not catching java.lang.StackOverflowError?有关,但不完全相同。我在这里不使用Try。核心问题是Future根本不会返回。我无法捕获任何错误,因为它只是挂起。

最佳答案

reporter工具用于灾难,它仅挂接到线程的UncaughtExceptionHandler,但似乎仅使用默认线程工厂即可立即使用:

scala 2.13.0-M5> import concurrent._,java.util.concurrent.Executors
import concurrent._
import java.util.concurrent.Executors

scala 2.13.0-M5> val ec = ExecutionContext.fromExecutor(null, e => println(s"Handle: $e"))
ec: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl$$anon$3@5e7c141d[Running, parallelism = 4, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]

scala 2.13.0-M5> val f = Future[Int](throw new NullPointerException)(ec)
f: scala.concurrent.Future[Int] = Future(<not completed>)

scala 2.13.0-M5> f
res0: scala.concurrent.Future[Int] = Future(Failure(java.lang.NullPointerException))

scala 2.13.0-M5> val f = Future[Int](throw new StackOverflowError)(ec)
Handle: java.lang.StackOverflowError
f: scala.concurrent.Future[Int] = Future(<not completed>)


scala 2.13.0-M5> val ec = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor, e => println(s"Handle: $e"))
ec: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@317a118b

scala 2.13.0-M5> val f = Future[Int](throw new StackOverflowError)(ec)
f: scala.concurrent.Future[Int] = Future(<not completed>)
Exception in thread "pool-1-thread-1" java.lang.StackOverflowError
    at $line14.$read$$iw$$iw$$iw$$iw$.$anonfun$f$1(<console>:1)
    at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659)
    at scala.util.Success.$anonfun$map$1(Try.scala:261)
    at scala.util.Success.map(Try.scala:209)
    at scala.concurrent.impl.Promise$Transformation.doMap(Promise.scala:420)
    at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:402)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

您可以构建一个设备,该设备在运行时记录 future ,并且可以安全地知道线程何时耗尽。例如,也许您想重试具有较低最大递归深度的算法。

关于scala - 为什么我的Scala future 无法传播错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53859710/

相关文章:

scala - 获取脚本文件名并打印它

scala - 无法证明与路径相关类型的等效性

error-handling - 我使用 Simply Fortran,但不能在那里包含模块

AngularJS:$log 和 console.log 有什么区别?

scala - 在Scala的Seq中添加项目

java - 将 R 集成到 Java Web 应用程序中

c# - 返回对象时如何抛出异常?

c# - 处理由无法访问的数据库引起的 NHibernate 延迟加载异常

c++ - 从捕获中重新抛出

node.js - 使用 Node.js 流管道进行超时处理