在 Scala 2.10 中使用 Future。它们是 Scala 团队、Akka 团队和 Twitter 之间的联合工作,旨在实现更标准化的未来 API 和跨框架使用的实现。我们刚刚在以下位置发布了指南:http://docs.scala-lang.org/overviews/core/futures.html http://docs.scala-lang.org/overviews/core/futures.html
除了完全非阻塞(默认情况下,尽管我们提供了执行托管阻塞操作的能力)和可组合性之外,Scala 2.10 futures 还带有一个隐式线程池来执行任务,以及一些管理超时的实用程序。
import scala.concurrent.{future, blocking, Future, Await, ExecutionContext.Implicits.global}
import scala.concurrent.duration._
// Retrieve URLs from somewhere
val urls: List[String] = ...
// Download image (blocking operation)
val imagesFuts: List[Future[...]] = urls.map {
url => future { blocking { download url } }
}
// Do something (display) when complete
val futImages: Future[List[...]] = Future.sequence(imagesFuts)
Await.result(futImages, 10 seconds).foreach(display)
上面,我们首先导入了一些东西:
-
future
:创造未来的API。
-
blocking
:用于托管阻塞的API。
-
Future
:Future 伴随对象,其中包含许多有用的方法收藏品期货。
-
Await
:用于阻塞未来的单例对象(将其结果传输到当前线程)。
-
ExecutionContext.Implicits.global
:默认的全局线程池,一个ForkJoin池。
-
duration._
:用于管理超时持续时间的实用程序。
imagesFuts
与您最初所做的大致相同 - 这里唯一的区别是我们使用托管阻塞 -blocking
。它通知线程池您传递给它的代码块包含长时间运行或阻塞操作。这允许池暂时生成新的工作人员,以确保永远不会发生所有工作人员都被阻塞的情况。这样做是为了防止阻塞应用程序中的饥饿(锁定线程池)。请注意,线程池还知道托管阻塞块中的代码何时完成,因此它将删除此时的空闲工作线程,这意味着池将缩小回其预期大小。
(如果你想绝对阻止创建额外的线程,那么你应该使用 AsyncIO 库,例如 Java 的 NIO 库。)
然后我们使用Future伴生对象的集合方法来转换imagesFuts
from List[Future[...]]
to a Future[List[...]]
.
The Await
对象是我们如何确保display
在调用线程上执行--Await.result
只是强制当前线程等待,直到它传递的未来线程完成。 (这在内部使用托管阻塞。)