【发布时间】:2022-02-04 09:38:01
【问题描述】:
如果我希望我的 Scala Future 返回一个值,可以通过等待结果/就绪来保证执行,例如 -
def longCalculation: Int = {
Thread.sleep(2000)
42
}
implicit val executionContext = scala.concurrent.ExecutionContext.global
val aFuture: Future[Int] = Future {
longCalculation
// throw new ArrayIndexOutOfBoundsException // non-fatal exception
// throw new StackOverflowError() // fatal exception
}
评估返回具体值的 Future -
val ready_aFuture_1: Future[Int] = Await.ready(aFutureTest, Duration.Inf)
val ready_aFuture_2: Option[Try[Int]] = ready_aFuture_1.value
val ready_aFuture_3: Try[Int] = ready_aFuture_2.get // will never be None, Option is unnecessary.
val ready_aFuture_4: String = ready_aFuture_3 match {
case Success(t) => t.toString
case Failure(e) => e.toString
}
println(ready_aFuture_4)
如果我想操纵未来的副作用,我能找到的唯一可以保证执行的方法是 -
val f: Future[Unit] = aFuture.map{ v =>
println(s"the result of aFuture map is: $v")
}
Await.result(f, Duration.Inf)
但这很丑陋,既因为我使用 .map 来表示“副作用”,又因为我们需要保留和使用 Unit 类型。
有没有其他方法可以保证对 Future 的处理会产生“副作用”?
【问题讨论】:
-
我不知道你为什么认为
map或Unit是“丑陋的”。在我看来,两者都很好。或者按照答案中的建议使用andThen(我发现它不太方便,因为它需要Try,但有时它实际上很有用,这取决于您要如何处理故障)。在我的书中你的 sn-p 中“最丑”的部分是Await...在大多数情况下,设计良好的代码不应该显式地等待副作用发生(如果你需要等待它,它是不是真正的副作用)。但是,这当然是“基于意见的”,所以我投票结束这个问题:) -
我认为 map 很丑,因为在纯函数式编程中 map 不应该产生副作用,而不是 foreach。此外,我不同意在设计良好的代码中我不应该显式执行 Wait 因为 wait 的目的是为了保证,我的意思是在我的实际场景编程问题中,在 99% 的情况下它是不需要的,但是在生产过程我们要保证我们的执行力。
-
在 pure 函数式编程中没有副作用 :) 一旦有了副作用,它就不是纯粹的,产生它的函数的名称并不重要.无论如何,如果您不喜欢
map,请按照建议使用andThen。我不知道您所说的“必须保证执行”到底是什么意思,但是保证副作用存在的正确方法,如果要查看副作用,而不是阻塞等待函数返回的线程.. . 什么都没有(如果它实际上返回了有用的东西,不暗示阻塞会更合理)。 -
WDYM的执行能保证吗?顺便说一句,也许你想改用
foreach? -
我的意思是,在退出主线程之前,我们要保证side-effect方法已经执行并且执行完毕。 foreach 是不够的,因为主线程可以在 foreach 之前结束。
标签: java multithreading scala jvm