一旦收到分子和分母,下面的演员就会进行分裂,
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 _ =>
}
}
是否有更可扩展的方式来聚合所有消息?
答案 0 :(得分:1)
标识请求的唯一标识符是解决问题的一种方法。 Actor内的地图(calcRegistry
)包含之前到达的FractionComponent
(Numerator
或Denominator
)。一旦该对的第二部分进入,我们就可以开始运行您已经完成的计算。
实施仍然没有解决内存泄漏的问题,其中第二对将不会被接收并且地图将继续增长。
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