2016-06-11 78 views
3

如果有方法可以限制Scala中未处理期货的数量,我无法支付资金。 例如在下面的代码:如何限制Scala中未处理期货的数量?

import ExecutionContext.Implicits.global  
for (i <- 1 to N) { 
    val f = Future { 
    //Some Work with bunch of object creation 
    } 
} 

如果N太大,它最终会抛出OOM。 有没有办法限制未处理的期货以数量队列式的等待或异常?

+2

这是一般情况,并不仅限于与期货合作。如果你正在创建/保留大量的任何类型的对象,那么你最终会耗尽内存。这是你的责任,适当限制这一点。 – JimN

回答

5

因此,最简单的答案是,您可以创建一个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并发执行。

+0

这很有帮助。非常感谢链接到maven和whatnot的上下文! – EdgeCaseBerg