我应该覆盖默认的ExecutionContext吗?

时间:2013-05-30 10:56:11

标签: scala concurrency

在scala中使用future时,默认行为是使用默认的Implicits.global执行上下文。似乎默认情况下每个处理器可以使用一个线程。在一个更传统的线程Web应用程序中,当期货执行诸如等待数据库(而不是某些cpu绑定任务)之类的任务时,这似乎是一个糟糕的默认值。

我希望覆盖默认上下文在生产中是相当标准的,但我可以找到关于这样做的文档很少,似乎它可能不常见。我错过了什么吗?

3 个答案:

答案 0 :(得分:40)

不要将其视为覆盖默认执行上下文,而是不要问“我应该为不同的事情使用多个执行上下文吗?”如果这是问题,那么我的回答是肯定的。在我工作的地方,我们使用Akka。在我们的应用程序中,我们使用默认的Akka执行上下文来实现非阻塞功能。然后,因为当前没有好的非阻塞jdbc驱动程序,所有阻塞SQL调用都使用单独的执行上下文,其中我们有每个连接的线程方法。保持主要执行上下文(fork join pool)不受阻塞会导致我们的吞吐量显着增加。

我认为在系统中为不同类型的工作使用多个不同的执行上下文是完全可以的。它对我们很有用。

答案 1 :(得分:3)

“正确”的答案是,需要使用ExecutionContext的方法需要在其签名中使用ExecutionContext,因此您可以从“外部”提供ExecutionContext来控制更高级别的执行。

答案 2 :(得分:2)

是的,在您的应用程序中创建和使用其他执行上下文绝对是个好主意。

执行上下文将模块化您的并发模型并隔离应用程序的不同部分,这样如果应用程序的某个部分出现问题,其他部分将受此影响较小。要考虑您的示例,您将拥有针对特定于数据库的操作的不同执行上下文,而另一个例如处理Web请求。

在Jonas Boner的this presentation中,这种模式被称为在您的应用程序中创建“Bulkheads”以获得更高的稳定性&容错。

我必须承认,我自己并没有多少关于执行上下文的使用。但是,我确实看到这个原则适用于某些框架。例如,Play将针对不同类型的作业使用不同的执行上下文,并鼓励您在必要时将任务拆分到不同的池中:Play Thread Pools

Akka中间件还建议将应用程序拆分为应用程序中不同并发区域的不同上下文。他们使用Dispatcher的概念,这是电池的执行环境。

此外,scala并发库中的大多数运算符都需要执行上下文。这是为了给您提供在模块化应用程序并发性时所需的灵活性。