【问题标题】:Handling unexpected exceptions on scala Futures处理 scala Futures 上的意外异常
【发布时间】:2014-09-07 11:15:23
【问题描述】:

当使用如下代码时:

scala> Future { null } onComplete { case Success(v) => v.toString }

Scala 抛出以下异常:

scala> java.lang.NullPointerException
    at $line14.$read$$iw$$iw$$anonfun$2.apply(<console>:11)
    at $line14.$read$$iw$$iw$$anonfun$2.apply(<console>:11)
    at     scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
    at     scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107)
    at     scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at     scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at     scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at     scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

这没关系,因为我没有处理任何异常。问题是我的应用程序完全挂起。

我正在使用concurrent.ExecutionContext.Implicits.global,我认为onComplete 是在这个全局执行上下文中执行的。问题是执行上下文似乎停止接受任何工作并且应用程序只是挂起。

我是否必须明确使用try ... catch,以便在onComplete 发生意外情况时保护我的应用程序?

谢谢

【问题讨论】:

  • 你能在未来的上下文中执行潜在的不安全操作吗?例如。 Future(null).map(_.toString).onComplete { ... }.
  • 导致空指针异常只是我发现在没有明确使用throw 的情况下导致异常的方式。我真的没有“潜在不安全”的操作,我在onComplete 子句中的所有内容都是可能导致异常的代码..

标签: scala concurrency future


【解决方案1】:

IIRC,这只是最早实施中的问题。

您可以提供处理程序或“报告者”:

scala> import util._
import util._

scala> import concurrent._
import concurrent._

scala> ExecutionContext.fromExecutor(null, (t: Throwable) => println(s"Hi, $t"))
res0: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@221a3fa4

scala> implicit val x = res0
x: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@221a3fa4

scala> Future { null } onComplete { case Success(v) => v.toString }
<console>:16: warning: match may not be exhaustive.
It would fail on the following input: Failure(_)
              Future { null } onComplete { case Success(v) => v.toString }
                                         ^
Hi, java.lang.NullPointerException

scala> 

一切都处理好了。

【讨论】:

  • 我还是有同样的问题,应用程序挂了,只是异常报告的方式不同,“嗨,”..谢谢
  • 我的意思是,您的回调已经包含在尝试中,它将呼叫您的记者。什么scala版本,你确定它不是应用程序级死锁吗?执行线程转储以检查池正在处理的内容。
  • 你是对的。由于 onComplete 在不同的执行程序上运行,如果它失败,我的演员不会抛出异常并且不会死,所以主管永远不会重新启动它,所以我的应用程序陷入僵局。我发现使用 maprecover工作得更好,因为未来执行和地图回调中的所有异常都在recover 中处理。谢谢
【解决方案2】:

首先,你得到的NullPointerException与未来无关;它不会发生在 Future 块内。

您可以做的是将可能返回 null 的代码封装在 Option() 中。
您的代码将如下所示:

Future { Option(mightBeANull) } onComplete { case Success(v) => v.map(_.toString) }

【讨论】:

  • 这将解决意外空值的问题,但并不是我的onComplete 回调中可能发生的所有异常。使用NullPointerException 只是一个示例
  • @simao:onComplete 块内发生的事情与异常无关,因此您可以按照自己的方式处理它。
猜你喜欢
  • 2011-08-08
  • 2022-08-13
  • 1970-01-01
  • 2014-01-15
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
相关资源
最近更新 更多