我有一个返回Try
的函数,并且我想并行运行它的多个实例,但是我在如何做到这一点方面空白–我似乎只能运行一个接一个。
上下文:此函数用于获取锁定,因此,如果多个线程/工人并行运行,则它们不会互相读取对方的脚趾。在测试中,我想同时运行五个实例,并断言除了其中一个实例外,其他所有实例均被锁定。当函数返回Future时,此方法起作用了,但是我做了一些重构,现在返回了Try,并且测试已停止工作。
该行为似乎与锁定代码无关-似乎我不了解并发!
我一直在尝试使用Future.fromTry
并并行执行它们。例如:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Success, Try}
object Main extends App {
def greet(name: String): Try[Unit] = Try {
println(s"Hello $name!")
Thread.sleep(1000)
println(s"Goodbye $name!")
()
}
Seq("alice", "bob", "carol", "dave", "eve").map { name =>
Future.fromTry { greet(name) }
}
}
我希望看到所有的“ Hello”消息,然后看到所有的“ Goodbye”消息-相反,它似乎是一个接一个地执行它们。
Hello alice!
Goodbye alice!
Hello bob!
Goodbye bob!
Hello carol!
Goodbye carol!
Hello dave!
Goodbye dave!
Hello eve!
Goodbye eve!
我环顾四周,发现了有关调整ExecutionContext并添加并行性的建议–事实是,在这种环境下并行运行Futures似乎非常高兴。
在同一台机器上,使用相同的全局ExecutionContext,如果我调整函数以返回Future(而不是Try),那么我将看到期望的输出,并且这些函数似乎正在并行运行。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Success, Try}
object Main extends App {
def greet(name: String): Future[Unit] = Future {
println(s"Hello $name!")
Thread.sleep(1000)
println(s"Goodbye $name!")
()
}
Seq("faythe", "grace", "heidi", "ivan", "judy").map { name =>
greet(name)
}
Thread.sleep(2000) // Let the futures finish
}
Hello faythe!
Hello ivan!
Hello grace!
Hello judy!
Hello heidi!
Goodbye ivan!
Goodbye grace!
Goodbye heidi!
Goodbye judy!
Goodbye faythe!
Future.fromTry
在做什么,这意味着它正在等待期货交易完成?如何使其与第二个示例匹配?
还是我完全把错误的树种了?
答案 0 :(得分:3)
documentation明确声明fromTry
将根据结果创建已经 已完成的Future,因此它首先评估函数,然后提升在Future上下文中。因此,它是完全串行的。
您可以先根据名称创建一个List[Future[String]]
,然后映射列表并映射内部的Future以执行您的功能。
或者,由于Future已经表示可能发生故障(并且在内部使用Try),为什么不在函数(就像您之前所说的那样)中简单地使用Future。