如何将两个孩子演员的总和结果返回给父母并打印出来

时间:2019-04-05 00:53:03

标签: java akka

我正在尝试弄清楚如何使用父级收到的多个结果并将其发送给父级。

我对akka的基本知识掌握得很好,而且我知道如何传递消息并收到一个回复​​。当我需要将两个答复合并为一个结果(然后将该结果传递)时,我迷路了。

例如:   我要同时添加1,2,3,4。因此,我向一个孩子发送了包含1和2的消息,向另一个孩子发送了包含3和4的消息。他们将各自的数字相加,然后向父母发送回信,理想情况下,父母会相加2个结果。

3 个答案:

答案 0 :(得分:0)

假设akkajava有点相似,您可以这样做

firstMethod(arguments) + secondMethod(arguments),因为您要添加结果。 (根据返回值得出)

答案 1 :(得分:0)

您可以在父演员中保留一个簿记参数,因此在scala代码中,将是这样的:

object SumAggregationWorker {
  def props: Props = Props[SumAggregationWorker]
  case class ReceivedValue(value: Double) 
}

class SumAggregationWorker extends Actor {
  var totalSum: Int = 0

  override def receive: Receive = {
    case ReceivedValue(value) => 
      totalSum += value
  }
}

另一种方法是询问而不是告诉其他参与者,在这种情况下,您拥有与要求总和的参与者相同数量的期货。 通过理解,您可以计算最终值,但是以上是ud通常处理这些情况的方式。 因此,如果上述参与者发送了一些数字串给不同的参与者以计算总和,然后报告总和,则您可以在求和请求中保留一些ID,以便上方的参与者知道他希望接收多少总和以及ID进行汇总,然后可以在收到最后一笔款项后将结果发送出去。

for {
 a <- actor1 ? SumUp(valueList1)
 b <- actor3 ? SumUp(valueList2)
} yield extractFromResponse(a) + extractFromResponse(b)

其中extractFromResponse是一些函数,用于解释接收到的消息并提取计算出的值。 在产生的将来,您可以使用.onComplete调用将汇总结果发送给父级。

答案 2 :(得分:0)

以下是Scala中的解决方案,我相信可以将其转换为Java而不会带来太多麻烦。鉴于您的要求(即使用一批童工来集体执行计算任务),我建议使用router

这是一个由Master演员组成的准系统摘要,该演员将Add的工作委派给配置为Worker路由的round-robin子演员。在接收到来自子路径的工作结果后,var角色中将计算结果的Master保持可变,以进行增量更新。

import akka.actor.{Props, ActorSystem, Actor, ActorLogging}
import akka.routing.RoundRobinPool

case class CalcSum(l: List[Double])
case class Add(x: Double, y: Double)
case class Result(value: Double)
case object GetResult

class Worker extends Actor with ActorLogging {
  def sum(x: Double, y: Double): Result = Result(x + y)

  def receive = {
    case Add(x, y) =>
      sender ! sum(x, y)
    case _ =>
      log.error("Unknown work request!")
  }
}

class Master(nrOfWorkers: Int) extends Actor with ActorLogging {
  private var numbers: List[Double] = List.empty[Double]
  private var result: Double = 0.0
  private var nrOfWorkResults: Int = 0

  val workerRouter = context.actorOf(
    Props[Worker].withRouter(RoundRobinPool(nrOfWorkers)), name = "workerRouter"
  )

  def receive = {
    case CalcSum(l: List[Double]) =>
      numbers = l
      result = 0.0
      nrOfWorkResults = 0
      l.foreach(x => workerRouter ! Add(result, x))
    case Result(value) =>
      result += value
      nrOfWorkResults += 1
    case GetResult =>
      if (nrOfWorkResults < numbers.size - 1)
        log.info("Calculation still in progress ...  Please check again later.")
      else
        log.info(s"Result: $result")
  }
}

object Master {
  def props(nrOfWorkers: Int): Props = Props(new Master(nrOfWorkers))
}

请注意,这是一个非常基本的示例,例如可以通过context.become进行热交换功能进行完善,以最大限度地减少对可变var的需求,等等。

使用4个worker角色的路由器运行测试,以计算数值列表1到1,000,000的总和:

implicit val system = ActorSystem("system")
implicit val ec = system.dispatcher

val master = system.actorOf(Master.props(nrOfWorkers = 4), name = "master")

master ! CalcSum( List.iterate(1.0, 1000000)(_ + 1) )

master ! GetResult
// [INFO] [04/05/2019 14:20:44.747] [system-akka.actor.default-dispatcher-9]
//   [akka://system/user/master] Result: 5.000005E11

由于1到N的总和等于N * (N + 1) / 2,因此可以轻松地进行验证。