为什么我的Scala future不会传播错误?

为什么我的Scala future不会传播错误?,scala,exception,error-handling,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 pro

此代码按预期工作:

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")
}
第二次测试的未来永远不会回来。为什么
错误
子类(相对于
异常
子类)不会终止我的未来?我应该如何处理
错误
s


编辑:这可能与有关,但不完全相同。我没有在这里使用
尝试
。核心问题是未来根本不会回来;我无法从中捕获任何错误,因为它只是挂起。

正如评论中指出的,这是

根据Scala文档

注意:只有非致命异常才会在Try时被combinators捕获(请参见>scala.util.control.NonFatal)。另一方面,将>抛出严重的系统错误

没有可丢弃的->错误被Try捕获

还可以回答您关于通常如何进行错误处理的问题。 在Scala中,可以对可能导致异常的代码使用try/catch(非常类似于Java):

你应该首先有更具体的例外情况

您提供的代码如下所示:

我还试用了你的代码,它肯定会产生StackOverflower错误。
但是它不能像上面提到的链接所解释的那样正确地捕获它。

报告程序
功能是用于灾难的,它只是挂接到线程的
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>导入并发。\ java.util.concurrent.Executors
并发导入_
导入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[正在运行,并行度=4,大小=0,活动=0,运行=0,窃取=0,任务=0,提交=0]
scala 2.13.0-M5>val f=Future[Int](抛出新的NullPointerException)(ec)
f:scala.concurrent.Future[Int]=Future()
scala 2.13.0-M5>f
res0:scala.concurrent.Future[Int]=Future(失败(java.lang.NullPointerException))
scala 2.13.0-M5>val f=Future[Int](抛出新堆栈溢出错误)(ec)
句柄:java.lang.StackOverflowerr
f:scala.concurrent.Future[Int]=Future()
鉴于

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)
scala 2.13.0-M5>val ec=ExecutionContext.fromtexecutor(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](抛出新堆栈溢出错误)(ec)
f:scala.concurrent.Future[Int]=Future()
线程“pool-1-thread-1”java.lang.StackOverflowerr中出现异常
在$line14.$read$$iw$$iw$$iw$$iw$.$anonfun$f$1(:1)
在scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659)
在scala.util.Success.$anonfun$map$1(Try.scala:261)
在scala.util.Success.map(Try.scala:209)
位于scala.concurrent.impl.Promise$Transformation.doMap(Promise.scala:420)
在scala.concurrent.impl.Promise$Transformation.run处(Promise.scala:402)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
运行(Thread.java:748)

您可以构建一个在运行时注册未来的装备,以及一个知道线程何时崩溃的安全等待。例如,您可能希望重试具有较低最大递归深度的算法。

可能与此相关:不确定“它产生StackOverflower错误”的含义可能重复——当我运行它时,未来永远不会返回。考试就这么挂了。我想知道这是否是版本问题——我在2.11.8上(目前无法升级)。@Sasgorilla如果你点击链接,你可以在那里运行代码。它将在控制台中显示错误。这个错误无法捕捉。如果你勾选了重复的问题,答案是你需要试着抓住它。有道理吗?抱歉--我没有完全理解
try
的意思。在你的小提琴中,我仍然看到
等待
在30秒后超时。换句话说,我捕获的是一个
TimeoutException
,而不是
堆栈溢出错误。您能否使用
try
分享一个传播
StackOverflowerError
的示例?
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)