[英]Asynchronous IO in Scala with futures
假設我從一些URL下載了一個(可能很大的)圖像列表。 我正在使用Scala,所以我要做的是:
import scala.actors.Futures._
// Retrieve URLs from somewhere
val urls: List[String] = ...
// Download image (blocking operation)
val fimages: List[Future[...]] = urls.map (url => future { download url })
// Do something (display) when complete
fimages.foreach (_.foreach (display _))
我對Scala有點新意,所以對我來說這看起來仍然有些神奇:
display _
)是否會在主線程上執行,如果沒有,我該如何確定它? 謝謝你的建議!
在Scala 2.10中使用Futures。 他們是Scala團隊,Akka團隊和Twitter之間的聯合工作,以實現更加標准化的未來API和跨框架使用的實現。 我們剛剛發布了一份指南: http : //docs.scala-lang.org/overviews/core/futures.html
除了完全非阻塞(默認情況下,盡管我們提供了管理阻塞操作的能力)和可組合之外,Scala的2.10期貨還帶有一個隱式線程池來執行您的任務,以及一些管理超時的實用程序。
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
:未來的伴侶對象,其中包含許多有用的期貨收集方法。 Await
:用於阻止未來的單例對象(將其結果傳輸到當前線程)。 ExecutionContext.Implicits.global
:默認的全局線程池,一個ForkJoin池。 duration._
:用於管理超時duration._
實用程序。 imagesFuts
與您最初的工作基本相同 - 唯一的區別是我們使用托管阻塞blocking
。 它通知線程池您傳遞給它的代碼塊包含長時間運行或阻塞操作。 這允許池臨時生成新工作程序,以確保永遠不會發生所有工作程序被阻止的情況。 這樣做是為了防止阻塞應用程序中的飢餓(鎖定線程池)。 請注意,線程池還知道托管阻塞塊中的代碼何時完成 - 因此它將在該點刪除備用工作線程,這意味着池將縮減回其預期大小。
(如果您想絕對阻止創建其他線程,那么您應該使用AsyncIO庫,例如Java的NIO庫。)
然后我們使用Future伴隨對象的集合方法將imagesFuts
從List[Future[...]]
轉換為Future[List[...]]
。
Await
對象是我們如何確保在調用線程上執行display
的方法Await.result
只是強制當前線程等待,直到傳遞它的未來完成。 (這在內部使用托管阻止。)
val all = Future.traverse(urls){ url =>
val f = future(download url) /*(downloadContext)*/
f.onComplete(display)(displayContext)
f
}
Await.result(all, ...)
是的,對我來說似乎很好,但是你可能想要研究更強大的twitter-util或Akka Future API(Scala 2.10將有這種風格的新Future庫)。
它使用線程池。
不,它不會。 您需要使用GUI工具包的標准機制(Swing的SwingUtilities.invokeLater
或SWT的Display.asyncExec
)。 例如
fimages.foreach (_.foreach(im => SwingUtilities.invokeLater(new Runnable { display im })))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.