我正在研究一个scala项目,我决定在actor模型上使用Akka的代理库,因为它允许更多功能性的并发方法。但是,我遇到了运行很多不同的问题一次代理。看起来我只能同时运行三到四个代理。
import akka.actor._
import akka.agent._
import scala.concurrent.ExecutionContext.Implicits.global
object AgentTester extends App {
// Create the system for the actors that power the agents
implicit val system = ActorSystem("ActorSystem")
// Create an agent for each int between 1 and 10
val agents = Vector.tabulate[Agent[Int]](10)(x=>Agent[Int](1+x))
// Define a function for each agent to execute
def printRecur(a: Agent[Int])(x: Int): Int = {
// Print out the stored number and sleep.
println(x)
Thread.sleep(250)
// Recur the agent
a sendOff printRecur(a) _
// Keep the agent's value the same
x
}
// Start each agent
for(a <- agents) {
Thread.sleep(10)
a sendOff printRecur(a) _
}
}
上面的代码创建了一个代理,其中包含1到10之间的每个整数。底部的循环将printRecur函数发送给每个代理。程序的输出应该显示每隔一刻钟打印出的数字1到10(尽管不是以任何顺序)。但是,出于某种原因,我的输出只显示输出的数字1到4。
在Akka中使用代理是否有更规范的方法可行?我来自clojure背景并且之前已经成功使用过这种模式,所以我在Scala中天真地使用了相同的模式。
答案 0 :(得分:5)
我的猜测是你在4核盒子上运行,这也是你只看到数字1-4的部分原因。这里最重要的是你正在使用默认的执行上下文,我猜你的系统使用的线程池只有4个线程(每个核心一个)。通过这种以递归方式编码的方式,我的猜测是前4个代理从不放弃线程,它们是唯一可以打印任何东西的代理。
您可以通过删除以下行来轻松解决此问题:
import scala.concurrent.ExecutionContext.Implicits.global
在创建ActorSystem
import system.dispatcher
这将使用actor系统的默认调度程序,它是一个fork连接调度程序,它似乎与您在样本中导入的默认执行上下文没有相同的问题。
您还可以考虑使用send
而不是sendOff
,因为它将使用构建代理时可用的执行上下文。我认为当他们明确想要使用另一个执行上下文时,会使用sendOff
。