期货是否在Actors的receive方法中被阻止

时间:2016-02-09 17:14:11

标签: scala akka

只是一个问题: 我有一个查询db的actor(假设查询需要一些时间)。 db的所有结果都返回了Future。 这基本上就是我们这样做的方式:

case class BasePay(id:String,baseSalary)
class CalcActor(db:DB) extends Actor{
 override def receive: Receive = {
    case BasePay(id:String,baseSalary) => 
      for{
          person <- db.longQueryToFindPerson(id)
          calc <- db.anotherLongQueryCallCommission(person,baseSalary)
       }yield Foo(person,calc)
}

如果我在期货完成之前收到很多BasePay消息会怎样? 它在排队吗?我应该注意到其他失败吗?

3 个答案:

答案 0 :(得分:4)

  

如果我在期货完成之前收到很多BasePay消息会怎样?

许多期货将被执行,无论第一个期货何时完成。

  

排队了吗?

没有。让它排队的唯一方法是阻止Future结果。由于Future是异步调度的,因此actor可以继续处理消息。

  

我应该注意到其他失败吗?

这是一个广泛的问题。由于这看起来像示例代码,因此很难推测可能出现的问题。您可以通过同时分派许多查询来快速耗尽任何类型的连接池。这可以通过创建具有有限大小的ExecutionContext来限制同时执行多少Future个,但这不会限制演员快速接受消息。

答案 1 :(得分:1)

for comprehension使用上下文来执行代码

db.longQueryToFindPerson(id).flatMap(person => 
    db.anotherLongQueryCallCommission(person,baseSalary)
        .map(calc => Foo(person,calc))(aContext)//if no context will use implicit in this case the dispatcher assigned to the actor

这实际上是desugar into

   implicit val context = ExecutionContext.fromExecutor(//etc)
   for{
      person <- db.longQueryToFindPerson(id)
      calc <- db.anotherLongQueryCallCommission(person,baseSalary)
   }yield Foo(person,calc)

但是未来的flatmap需要运行一个上下文,因为没有提供它将使用隐式上下文

在这种情况下将使用分配给您的actor的调度程序,因此,您的actor将与正在执行的期货竞争线程分配。因此,您的演员将增加其邮箱,直到调度员能够处理期货。

你可以指定另一个调度员来运行期货,有不同的方法。

SELECT MagazineID, DispenserID, ProductID
FROM Magazine
WHERE ProductID = (SELECT ProductID 
                   FROM Magazine
                   WHERE MagazineID= 41659)
  AND DispenserId = (SELECT DispenserID 
                     FROM Magazine
                     WHERE MagazineID= 41659)

答案 2 :(得分:0)

如果这是默认邮箱,即你没有以某种方式指定邮箱,那么它的非阻塞和无限制,所以只要你的内存不足就可以了。 查看documentation以获取更多信息。