2017-05-07 47 views
1

我曾經認爲Try捕獲了跨線程異常,如下例所示。我猜不是的:那麼如何在生成的子線程中捕獲異常呢?Scala:如何捕獲子線程中的異常

// Simple class that throws error 
class Child extends Runnable { 
    def run { 
    val exception: Exception = new Exception("Foo") 
    val i = 1 
    Thread.sleep(1000) 
    val lines = scala.io.Source.fromFile("/tmp/filefoobar.txt").mkString 
    Thread.sleep(1000) 
    } 
} 
// spawn the class above 
def Parent() = { 
    val doit = Try { 
    val t = new Thread(new Child) 
    t.start 
    t.join() 
    } 

    doit match { 
    case Success(v) => println("uh oh did not capture error") 
    case Failure(v) => println("good we caught the error") 
    } 
} 

輸出 階>父()

Exception in thread "Thread-35" java.io.FileNotFoundException: /tmp/filefoobar.txt (No such file or directory) 
    at java.io.FileInputStream.open0(Native Method) 
    at java.io.FileInputStream.open(FileInputStream.java:195) 
    at java.io.FileInputStream.<init>(FileInputStream.java:138) 
    at scala.io.Source$.fromFile(Source.scala:91) 
    at scala.io.Source$.fromFile(Source.scala:76) 
    at scala.io.Source$.fromFile(Source.scala:54) 
    at $line120.$read$$iw$$iw$Child.run(<console>:16) 
    at java.lang.Thread.run(Thread.java:745) 
uh oh did not capture error 

回答

3

考慮使用期貨來處理異步任務的結果

import ExecutionContext.Implicits.global 
val resultFuture: Future[Unit] = Future { new Child.run } 
resultFuture.onComplete (result: Try[Unit] => ...) 
0

當兒童訪問該文件提出,其捕獲JRE並遵循默認行爲異常;打印堆棧跟蹤,然後將異常傳播到父進程,這會捕獲父級,如您在輸出中看到的那樣。

你可以做的是捕獲子進程中的異常並拋出異常,以便父進程可以處理它。

+0

.Are你說,如果重寫孩子作爲try塊並拋出異常,如果我發現錯誤,Parent會得到該異常?我如何「拋出自己」這個例外?畢竟,在代碼中,拋出錯誤並上升到堆棧,並且沒有到達父代。在孩子中明確拋出錯誤會做到這一點? – user7938511

0

您可以使用Thread.setUncaughtExceptionHandler設置例外,然後從嘗試重新拋出:

import java.lang.Thread.UncaughtExceptionHandler 

def Parent() = { 

    @volatile 
    var maybeException: Option[Throwable] = None 

    val doit = Try { 
    val target = new Child 
    val t = new Thread(target) 
    t.setUncaughtExceptionHandler(new UncaughtExceptionHandler { 
     override def uncaughtException(t: Thread, th: Throwable): Unit = { 
     maybeException = Some(th) 
     } 
    }) 
    t.start() 
    t.join() 

    maybeException.foreach(th => throw th) 
    } 

    doit match { 
    case Success(v) => println("uh oh did not capture error") 
    case Failure(v) => println("good we caught the error") 
    } 
} 
+0

上面的代碼不完全編譯。我得到一個:34:錯誤:類型不匹配; 實測值:(線程,Throwable的)=>單位 需要:java.lang.Thread.UncaughtExceptionHandler t.setUncaughtExceptionHandler((T:螺紋,E:Throwable的)=> { ^ – user7938511

+0

抱歉不懶惰,我曾嘗試修復它 – user7938511

+0

看起來你使用Scala 2.11,我的例子是2.12,所以我已經更新,所以它在2.11中工作。 –