미래가있는 Scala의 비동기 IO
일부 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를 처음 접했기 때문에 여전히 마술처럼 보입니다.
- 이것이 올바른 방법입니까? 그렇지 않은 경우 대안이 있습니까?
- 다운로드 할 이미지가 100 개있는 경우 한 번에 100 개의 스레드가 생성됩니까, 아니면 스레드 풀을 사용합니까?
- 마지막 명령어 (
display _
)가 메인 스레드에서 실행됩니까? 그렇지 않은 경우 어떻게 확인할 수 있습니까?
조언 해 주셔서 감사합니다!
Scala 2.10에서 선물 사용. 스칼라 팀, 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
: Future 컬렉션 에 유용한 여러 메소드를 포함하는 Future 컴패니언 객체입니다 .Await
: 퓨처 블록킹에 사용되는 싱글 톤 객체 (결과를 현재 스레드로 전송).ExecutionContext.Implicits.global
: 기본 전역 스레드 풀인 ForkJoin 풀.duration._
: 시간 초과 기간을 관리하기위한 유틸리티.
imagesFuts
remains largely the same as what you originally did- the only difference here is that we use managed blocking- blocking
. It notifies the thread pool that the block of code you pass to it contains long-running or blocking operations. This allows the pool to temporarily spawn new workers to make sure that it never happens that all of the workers are blocked. This is done to prevent starvation (locking up the thread pool) in blocking applications. Note that the thread pool also knows when the code in a managed blocking block is complete- so it will remove the spare worker thread at that point, which means that the pool will shrink back down to its expected size.
(If you want to absolutely prevent additional threads from ever being created, then you ought to use an AsyncIO library, such as Java's NIO library.)
Then we use the collection methods of the Future companion object to convert imagesFuts
from List[Future[...]]
to a Future[List[...]]
.
The Await
object is how we can ensure that display
is executed on the calling thread-- Await.result
simply forces the current thread to wait until the future that it is passed is completed. (This uses managed blocking internally.)
val all = Future.traverse(urls){ url =>
val f = future(download url) /*(downloadContext)*/
f.onComplete(display)(displayContext)
f
}
Await.result(all, ...)
- Use scala.concurrent.Future in 2.10, which is RC now.
- which uses an implicit ExecutionContext
- The new Future doc is explicit that onComplete (and foreach) may evaluate immediately if the value is available. The old actors Future does the same thing. Depending on what your requirement is for display, you can supply a suitable ExecutionContext (for instance, a single thread executor). If you just want the main thread to wait for loading to complete, traverse gives you a future to await on.
Yes, seems fine to me, but you may want to investigate more powerful twitter-util or Akka Future APIs (Scala 2.10 will have a new Future library in this style).
It uses a thread pool.
No, it won't. You need to use the standard mechanism of your GUI toolkit for this (
SwingUtilities.invokeLater
for Swing orDisplay.asyncExec
for SWT). E.g.fimages.foreach (_.foreach(im => SwingUtilities.invokeLater(new Runnable { display im })))
참고URL : https://stackoverflow.com/questions/13097754/asynchronous-io-in-scala-with-futures
'IT Share you' 카테고리의 다른 글
두 날짜 사이의 날짜 차이를 찾는 방법은 무엇입니까? (0) | 2020.11.10 |
---|---|
@Test 후 트랜잭션 롤백 (0) | 2020.11.10 |
CocoaPods의 의견? (0) | 2020.11.10 |
.NET에서 정수 목록 채우기 (0) | 2020.11.10 |
C ++ 용 매개 변수 파서 라이브러리는 무엇입니까? (0) | 2020.11.10 |