[英]Why does my Scala future not propagate an Error?
此代码按预期工作:
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")
}
在第二次测试中的未来永远不会回来。 为什么Error
子类(与Exception
子类相对)不能终止我的未来? 我应该如何处理Error
?
编辑:这可能与为何Scala尝试不捕获java.lang.StackOverflowError相关但不完全相同? 。 我不在这里使用“ Try
。 核心问题是, Future
永远不会回来。 我无法捕获任何错误,因为它只是挂起。
正如评论中指出的那样,这与“ 为什么Scala尝试不捕获java.lang.StackOverflowError?”的副本相同。
根据Scala文档。
注意:Try上的组合器仅捕获非致命异常(请参见> scala.util.control.NonFatal)。 另一方面,将引发严重的系统错误。
No Throwable-> Try捕获错误
还可以回答有关通常如何进行错误处理的问题。 在Scala中,您可以对可能导致异常的代码使用try / catch(非常类似于Java):
try {
// ... Your dangerous code in here
} catch {
case ioe: IOException => ... //
case e: Exception => ...
}
而且,您应该始终首先拥有更具体的例外。
您提供的代码如下所示: https : //scastie.scala-lang.org/2DJXJ6ESS9ySJZSwSodmZg
我也尝试了您的代码,它肯定会产生StackOverFlowerror。 但是它不能像上面提到的链接所说明的那样正确捕获它。
该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)
您可以构建一个可在运行时记录未来的装备,并安全地等待何时线程被炸毁。 例如,也许您想重试具有较低最大递归深度的算法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.