如何在Scala中使用actor时限制并发?

时间:2010-02-22 16:09:58

标签: scala concurrency actor

我来自Java,我将Runnable提交给由线程池支持的ExecutorService。在Java中非常清楚如何设置线程池大小的限制。

我对使用Scala actor感兴趣,但我不清楚如何限制并发。

假设我假设我正在创建一个接受“工作”的网络服务。提交的作业包含POST个请求,我希望我的服务将作业排入队列,然后立即返回202 Accepted - 即异步处理作业。

如果我使用actor来处理队列中的作业,我如何限制处理的同时作业的数量?

我可以想到几种不同的方法来解决这个问题;我想知道是否存在社区最佳实践,或者至少是一些明确建立的方法,这些方法在Scala世界中有些标准。

我想到的一种方法是拥有一个协调员角色来管理工作队列和工作处理角色;我想它可以使用一个简单的int字段来跟踪当前正在处理的作业数。我确信这种方法会有一些问题,例如确保跟踪何时发生错误以减少数量。这就是为什么我想知道Scala是否已经提供了更简单或更封装的方法。

BTW我试着提出这个问题a while ago,但我问得很糟糕。

谢谢!

3 个答案:

答案 0 :(得分:6)

我真的很鼓励你看看Akka,Scala的替代Actor实现。

http://www.akkasource.org

Akka已经有一个JAX-RS [1]集成,您可以与LoadBalancer [2]一起使用它来限制在并行中可以执行的操作数量:

[1] http://doc.akkasource.org/rest [2] http://github.com/jboner/akka/blob/master/akka-patterns/src/main/scala/Patterns.scala

答案 1 :(得分:5)

您可以覆盖限制actor线程池大小的系统属性actors.maxPoolSizeactors.corePoolSize,然后在您的actor可以处理的池中抛出尽可能多的作业。为什么你认为你需要限制你的反应?

答案 2 :(得分:3)

你真的有两个问题。

第一个是控制actor使用的线程池。这可以通过设置系统属性actors.maxPoolSize来完成。

第二个是提交到池中的任务数量的失控增长。您可能会或可能不会关注此问题,但是完全有可能通过过快地生成太多任务来触发内存错误等故障情况,并在某些情况下触发更微妙的问题。

每个工作线程都会保留一个任务队列。 dequeue实现为一个数组,工作线程将动态放大到某个最大大小。在2.7.x中,队列可以自己增长很大,我已经看到,当与大量并发线程结合使用时,会触发内存不足错误。最大出列尺寸小于2.8。出队也可以填补。

解决此问题需要您控制生成的任务数量,这可能意味着您已经概述了某种协调器。当启动一种数据处理管道的actor比管道中的后者快得多时,我遇到了这个问题。为了控制进程,我通常让链中的actor稍后在链中的每个X消息中ping回演员,并在X消息之后使链中的那些更早停止并等待ping回来。您也可以使用更集中的协调员来完成。