来自 Java 背景,在多个线程之间拆分多个任务的问题可以很容易地使用 ExecutorService 并通过该接口提交任务。你会说同样的方法在 Scala 世界中有意义吗?如果是这样,是否有该 API 的 Scala 版本?
如果没有,你会推荐什么方法?演员似乎有点矫枉过正,因为我认为它们主要用于线程通信......
来自 Java 背景,在多个线程之间拆分多个任务的问题可以很容易地使用 ExecutorService 并通过该接口提交任务。你会说同样的方法在 Scala 世界中有意义吗?如果是这样,是否有该 API 的 Scala 版本?
如果没有,你会推荐什么方法?演员似乎有点矫枉过正,因为我认为它们主要用于线程通信......
如果您不想走演员路线,那么您当然可以使用ExecutionContext
and 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
纯 Scala 方式
Scala 的并发模型基于 Erlang Actor 模型。这是一种略有不同的方法。要充分利用 Scala 的并发性,请使用 Akka 之类的东西。基本的使用思路相当简单。
最简单的任务是使用一个Future
(异步操作)。在此处阅读有关此内容的更多信息。Executors 框架不是您应该采用的方法。实现强大的多线程有很多选择| Scala 应用程序中的并行性:
Scala/Java 互操作性方法
Actor 可能对您习惯于实现并发的方式产生巨大的变化,而 Java 在这方面没有缺点。因此,您仍然可以在 Scala 应用程序中使用 Executor 框架进行多线程处理。
这意味着您将几乎完全依赖本机 Java 并发结构,但它使您不得不进行大量更改。在此处阅读有关如何在 Scala 中执行此操作的更多信息。
这是并行集合的一个很好的用例(如果任务相对繁重):
val TasksNumber = 27
val tasks = List.fill(TasksNumber) { () => Thread.sleep(10000) }
tasks.par.map(t => t.apply)