来自Java背景,在多个线程之间拆分多个任务的问题可以很容易地使用ExecutorService并通过该接口提交任务。你会说同样的方法在Scala世界中有意义吗?如果是这样,是否有该API的Scala版本?
如果不是,您会推荐什么方法?演员似乎有点矫枉过正,因为我认为它们主要用于线程通信......
答案 0 :(得分:3)
纯粹的Scala方式
Scala的并发模型基于Erlang actor模型。这是一种略有不同的方法。要充分利用Scala的并发性,请使用类似Akka的东西。基本的使用思路非常简单。
最简单的任务是使用Future
(异步操作)。阅读有关此HERE的更多信息。 Executors框架不是您应该采用的方法。有很多选项可以实现强大的多线程| Scala应用程序中的并行性:
答案 1 :(得分:3)
如果您不想参加演员路线,那么您当然可以使用ExecutionContext
和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
}
在这个例子中,Success
中的tup将按顺序包含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
函数返回的任何类型的List。
最后,如果你想执行一些基于序列的异步任务,你可以这样做:
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
的{{1}}。这只是表面上的问题。如果您有兴趣了解更多信息,请查看http://docs.scala-lang.org/overviews/core/futures.html
答案 2 :(得分:1)
这是parallel collections的一个很好的用例(如果任务比较繁重):
val TasksNumber = 27
val tasks = List.fill(TasksNumber) { () => Thread.sleep(10000) }
tasks.par.map(t => t.apply)