如何运行返回Try的函数的并行实例?

时间:2019-05-21 19:36:17

标签: scala concurrency

我有一个返回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在做什么,这意味着它正在等待期货交易完成?如何使其与第二个示例匹配?

还是我完全把错误的树种了?

1 个答案:

答案 0 :(得分:3)

documentation明确声明fromTry将根据结果创建已经 已完成的Future,因此它首先评估函数,然后提升在Future上下文中。因此,它是完全串行的。

您可以先根据名称创建一个List[Future[String]],然后映射列表并映射内部的Future以执行您的功能。
或者,由于Future已经表示可能发生故障(并且在内部使用Try),为什么不在函数(就像您之前所说的那样)中简单地使用Future。