4

来自 Java 背景,在多个线程之间拆分多个任务的问题可以很容易地使用 ExecutorService 并通过该接口提交任务。你会说同样的方法在 Scala 世界中有意义吗?如果是这样,是否有该 API 的 Scala 版本?

如果没有,你会推荐什么方法?演员似乎有点矫枉过正,因为我认为它们主要用于线程通信......

4

3 回答 3

3

如果您不想走演员路线,那么您当然可以使用ExecutionContextand Futures。如果你有一个隐含ExecutionContext的范围,你可以做这样的事情,如果你有一组固定的任务,你想同时运行:

val f1 = Future{
  //do something here
}  
val f2 = Future{
  //do something else here
} 
val aggFut = for{
  f1Val <- f1
  f2Val <- f2
} yield (f1Val, f2Val)

aggFut onComplete{
  case Success(tup) => //handle success case here
  case Failure(ex) => //handle failure here
}

在此示例中, tupSuccess将包含 f1 和 f2 按该顺序的结果。

如果您有动态数量的并行任务要运行,您可以执行以下操作:

val futs = someList.map(item => Future{...})
val aggFut = Future.sequence(futs)
aggFut onComplete{
  case Success(list) => //handle success case here
  case Failure(ex) => //handle failure here
}    

在这个成功案例中,将包装从函数Success返回的任何类型的列表。Future

最后,如果您想执行一些基于序列的异步任务集,您可以执行以下操作:

val fut = for{
  val1 <- Future{...}
  val2 <- Future{...}
} yield val2
fut onComplete{
  case Success(v2) => //handle success case here
  case Failure(ex) => //handle failure here
} 

在这种情况下,该值val1将可用于Future正在计算的val2。这只是真正触及表面。如果您有兴趣了解更多信息,请查看http://docs.scala-lang.org/overviews/core/futures.html

于 2013-04-24T00:11:27.183 回答
3

纯 Scala 方式

Scala 的并发模型基于 Erlang Actor 模型。这是一种略有不同的方法。要充分利用 Scala 的并发性,请使用 Akka 之类的东西。基本的使用思路相当简单。

最简单的任务是使用一个Future(异步操作)。在此处阅读有关此内容的更多信息。Executors 框架不是您应该采用的方法。实现强大的多线程有很多选择| Scala 应用程序中的并行性:

  1. 阿卡
  2. Lift actor(使用 Lift web 框架时)。
  3. Finagle(Twitter RPC 框架)。
  4. 默认的 Scala 演员库,在 Scala 2.10 中已弃用。在这里阅读更多。

Scala/Java 互操作性方法

Actor 可能对您习惯于实现并发的方式产生巨大的变化,而 Java 在这方面没有缺点。因此,您仍然可以在 Scala 应用程序中使用 Executor 框架进行多线程处理。

这意味着您将几乎完全依赖本机 Java 并发结构,但它使您不得不进行大量更改。在此处阅读有关如何在 Scala 中执行此操作的更多信息。

于 2013-04-23T19:20:30.317 回答
1

这是并行集合的一个很好的用例(如果任务相对繁重):

val TasksNumber = 27
val tasks = List.fill(TasksNumber) { () => Thread.sleep(10000) }
tasks.par.map(t => t.apply)
于 2013-04-23T19:19:10.553 回答