def testThrowException(number: Int): Future[Int] = {
if (number == 0) {
throw new Exception("number is 0")
else {
Future{1}
}
对于上述功能,如果我使用testThrowException(0)进行调用,则可以看到控制台中打印的异常错误消息 但是如果我做类似的事情
def testThrowException(number: Int): Future[Int] = {
anotherFuture.map {
if (number == 0) {
throw new Exception("number is 0")
} else {
1
}
}
我看不到控制台中打印的异常 但是,如果我执行testThrowException.onFailure,则可以看到失败消息,这里我做错了什么吗?为什么没有打印出异常
答案 0 :(得分:3)
在第一个示例中,异常就是这样,遇到时会抛出一个裸异常。与这样的事情没什么大不同。
def testThrowException(number: Int): Future[Int] = {
throw new Exception("BOOM!")
. . . //code to create a Future[Int]
第二个示例在Fututre
内引发异常。异常包装在Future
中,导致其失败。您将不会看到任何内容发送到控制台,但是如果您检查结果值,您应该会看到想要的内容。
res0: scala.concurrent.Future[Int] = Future(Failure(java.lang.Exception: number is 0))
答案 1 :(得分:3)
Future
在单独的线程中运行,因此在Future
中投掷只会使该线程崩溃,而使主线程仍在运行。例如,
object Hello extends App {
println(s"Starting in main thread called ${Thread.currentThread.getName}...")
Future(
throw new RuntimeException(s"I crashed separate thread called ${Thread.currentThread.getName}")
).andThen { case Failure(e) => println(e.getMessage) }
println("I made it!")
}
应输出
Starting in main thread called run-main-e...
I made it!
I crashed separate thread called scala-execution-context-global-253
我们看到它崩溃了一个名为scala-execution-context-global-253
的单独线程,而主线程run-main-e
仍在运行,因此I made it!
可以正常打印了。另一方面,以下示例将Future
object Hello extends App {
println(s"Starting in main thread called ${Thread.currentThread.getName}...")
throw new RuntimeException(s"I crashed the main thread ${Thread.currentThread.getName}")
println("I made it!")
}
输出
Starting in main thread called run-main-d...
[error] (run-main-d) java.lang.RuntimeException: I crashed the main thread run-main-d
我们看到主线程run-main-d
在可以打印I made it!
之前崩溃了。
答案 2 :(得分:2)
第一个函数testThrowException
在获得0
作为输入的情况下不会返回Future。因此,该程序将一直运行直到出现异常。
但是,如下面粘贴的源代码所示,Future.map
总是返回另一个未来:
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity)
val p = Promise[S]()
onComplete { v => p complete (v map f) }
p.future
}
仅定义Future不会打印其结果,也不会打印抛出的异常。为此,您需要定义onSuccess
,onFailure
或onComplete
。但是,如果将来的正文中存在打印语句,则它将执行:
def addOne(number: Int): Int = {
if (number == 0) {
// you can also print the exception instead of just throwing it.
throw new Exception("number is 0")
} else {
println("success")
1 + number
}
}
Future { addOne(1) } // scala.concurrent.Future[Int] = Future(Success(2))
// the above also prints "success"
Future { addOne(0) } // scala.concurrent.Future[Int] = Future(Failure(java.lang.Exception: number is 0))
// the above does not print anything unless the exception is printed before thrown in `addOne`
您也可以使用onComplete
处理成功和/或失败:
// prints "got error" plus the stack trace
- List item
Future {0}.map(addOne).onComplete {
case Success(value) => println(s"got $value")
case Failure(t) => println("got error: " + t.getStackTrace.mkString("\n"))
}
请注意,使用的进口是:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}