因此,最简单的答案是,您可以创建一个ExecutionContext
,用于阻止或限制新任务的执行超出特定限制。见this blog post。有关阻塞Java ExecutorService
的更丰富的示例,请参阅an example。 [您可以直接使用它,Maven Central上的库是here。]这封装了一些非阻塞ExecutorService
,您可以使用java.util.concurrent.Executors
的工厂方法创建它。
要将Java ExecutorService
转换为Scala ExecutionContext
只是ExecutionContext.fromExecutorService(executorService)
。因此,使用上面链接库,你可能有这样的代码......
import java.util.concurrent.{ExecutionContext,Executors}
import com.mchange.v3.concurrent.BoundedExecutorService
val executorService = new BoundedExecutorService(
Executors.newFixedThreadPool(10), // a pool of ten Threads
100, // block new tasks when 100 are in process
50 // restart accepting tasks when the number of in-process tasks falls below 50
)
implicit val executionContext = ExecutionContext.fromExecutorService(executorService)
// do stuff that creates lots of futures here...
,如果你想有界ExecutorService
,将持续,只要你的整个应用程序这很好。但是,如果您在代码中的本地化点创建大量期货,并且您将在完成后关闭ExecutorService
。我define loan-pattern methods in Scala [maven central]这两个创建上下文,并在我完成后关闭它。该代码最终看起来像...
import com.mchange.sc.v2.concurrent.ExecutionContexts
ExecutionContexts.withBoundedFixedThreadPool(size = 10, blockBound = 100, restartBeneath = 50) { implicit executionContext =>
// do stuff that creates lots of futures here...
// make sure the Futures have completed before the scope ends!
// that's important! otherwise, some Futures will never get to run
}
而不是使用一个ExecutorService
,阻止顾左右而言他,你可以使用强制任务调度(Future
-creating)Thread
执行会减慢速度实例任务而不是异步运行它。您将使用ThreadPoolExecutor.CallerRunsPolicy
来制作java.util.concurrent.ThreadPoolExecutor
。但是ThreadPoolExecutor直接构建起来相当复杂。
一个较新的,更性感,更斯卡拉为中心的替代所有的这将是签出Akka Streams作为替代Future
用于与“背压”,以防止OutOfMemoryErrors
并发执行。
这是一般情况,并不仅限于与期货合作。如果你正在创建/保留大量的任何类型的对象,那么你最终会耗尽内存。这是你的责任,适当限制这一点。 – JimN