簡體   English   中英

Akka actor 消息聚合

[英]Akka actor messages aggregate

一旦收到分子和分母,以下參與者執行除法,

package funnelTest

import akka.actor.{Actor, ActorSystem, Props}

object Main extends App {

  val system1 = ActorSystem("funnelTest")
  val input  = system1.actorOf(Props[Funnel], "input")

  input ! 3
  input ! 2.718

}

case object Run

class Funnel extends Actor {

  var i: Option[Int] = None
  var d: Option[Double] = None

  def isReady = i.nonEmpty && d.nonEmpty

  def receive = {
    case v: Int    => i = Some(v) ; if (isReady) self ! Run
    case v: Double => d = Some(v) ; if (isReady) self ! Run
    case Run       => println(s"aggregated, $d / $i = " + d.get/i.get)
    case _         =>  
  }
}

是否有更可擴展的方式來聚合所有消息?

標識請求的唯一標識符是解決問題的一種方法。 calcRegistry內的映射 ( calcRegistry ) 包含先前到達的FractionComponentNumeratorDenominator )。 一旦對的第二部分出現,我們就可以像您已經完成的那樣開始運行計算。

該實現仍然沒有解決內存泄漏的問題,即不會收到第二對並且地圖會繼續增長。

import akka.actor.{Actor, ActorSystem, Props}

object Main extends App {

  import Funnel._

  val system1 = ActorSystem("funnelTest")
  val input = system1.actorOf(Props[Funnel], "input")

  (1 to 10) foreach { number =>

    val id = java.util.UUID.randomUUID().toString
    input ! Numerator(id, value = number + 2)
    input ! Denominator(id, value = number + 1)
  }

  system1.awaitTermination()

}

class Funnel extends Actor {

  import Funnel._
  import scala.collection._

  val calcRegistry = mutable.Map[String, FractionComponent]()

  def saveToRegistry(comp: FractionComponent) = calcRegistry(comp.id) = comp

  def printValue(num: Numerator, den: Denominator) = println(s"aggregated, ${num.value} / ${den.value} = ${num.value / den.value}")

  def receive = {
    case num@Numerator(id, _) =>
      if (calcRegistry contains id)
        self ! Run(num, calcRegistry(id).asInstanceOf[Denominator])
      else saveToRegistry(num)
    case den@Denominator(id, _) =>
      if (calcRegistry contains id)
        self ! Run(calcRegistry(id).asInstanceOf[Numerator], den)
      else saveToRegistry(den)
    case Run(num: Numerator, den: Denominator) =>
      calcRegistry.remove(num.id)
      printValue(num, den)
    case _ =>
  }
}

object Funnel {

  sealed trait FractionComponent {
    def id: String
  }

  case class Numerator(override val id: String, value: Double) extends FractionComponent

  case class Denominator(override val id: String, value: Integer) extends FractionComponent

  case class Run(num: Numerator, denominator: Denominator)

}

示例輸出:

aggregated, 3.0 / 2 = 1.5
aggregated, 4.0 / 3 = 1.3333333333333333
aggregated, 5.0 / 4 = 1.25
aggregated, 6.0 / 5 = 1.2
aggregated, 7.0 / 6 = 1.1666666666666667
aggregated, 8.0 / 7 = 1.1428571428571428
aggregated, 9.0 / 8 = 1.125
aggregated, 10.0 / 9 = 1.1111111111111112
aggregated, 11.0 / 10 = 1.1
aggregated, 12.0 / 11 = 1.0909090909090908

參考:使用 Actor 模型的反應式消息傳遞模式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM