簡體   English   中英

為什么我的Scala未來無法傳播錯誤?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM