阿卡:怎么得到结果?

时间:2014-10-17 10:29:07

标签: scala akka

考虑以下使用Akka计算阶乘的Scala代码。我不知道如何获得输出。

import scala.annotation.tailrec
import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
import scala.concurrent.Await
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._

case class GetResult() 

class FactorialCalculator extends Actor {
  def receive = {
    case num: Int => sender ! (num, factor(num))
  }

  private def factor(num: Int) = factorTail(num, 1)

  @tailrec private def factorTail(num: Int, acc: BigInt): BigInt = {
    (num, acc) match {
      case (0, a) => a
      case (n, a) => factorTail(n - 1, n * a)
    }
  }
}

class FactorialCollector(factorials: List[Int]) extends Actor with ActorLogging {
  var list: List[BigInt] = Nil
  var size = factorials.size

  for (num <- factorials) {
    context.actorOf(Props(new FactorialCalculator)) ! num
  }

  def receive = {
    case (num: Int, fac: BigInt) => {
      log.info(s"factorial for $num is $fac")

      list = fac :: list
      size -= 1

      if (size == 0) {
        log.info(list.toString)
        context.system.shutdown()
      }
    }

    case GetResult => sender ! list
  }
}

class Factorial(factorials: List[Int]) {

  val system = ActorSystem("factorial")

  val collector = system.actorOf(Props(new FactorialCollector(factorials)), "collector")

    implicit val timeout = Timeout(10 seconds)
    val future = collector ? GetResult
    val result = Await.result(future, timeout.duration)

    system.awaitTermination()
}


var x = new Factorial(List(50, 18, 32, 28, 22, 42, 55, 48))

结果存储在课程list中计算的变量FactorialCollector中,但x.result会返回空的list

2 个答案:

答案 0 :(得分:1)

首先,您不应该使用表单context.actorOf(Props(new FactorialCalculator)),但是: context.actorOf(Props[FactorialCalculator]) source

其次,您可以将messege发送到FactorialCollector for anwser,例如:

def receive = {
  ....
  case GiveMeResult => sender ! list
  ....
}

或者不是在列表中给出要在构造函数中计算的整数,而是可以通过ask方法将它发送给Collector。然后你最后得到计算结果的未来。

答案 1 :(得分:0)

您将GetResult消息发送到FactorialCollector BEFORE收集器收到FactorialCalculators的所有结果

相反

for (num <- factorials) {
    context.actorOf(Props(new FactorialCalculator)) ! num
  }

你需要

val res = Await.result(Future.traverse(factorials)(context.actorOf(Props(new FactorialCalculator)) ? _), timeout)

但Await很难看 - 不要和akka一起使用:)。

阅读stash / unstashAll和context.become(..)

相关问题