【发布时间】:2018-09-29 10:25:45
【问题描述】:
考虑我在同一个演员系统中有四个演员(1,2,3,4)。每个演员只能与尚未向其发送消息的邻居发送消息(即 1 只能发送给 2 和4. 2 和 4 也只能发送给 3,因为他们的邻居 1 已经发送了消息)。当一个演员从它的邻居那里收到消息时,它会打印它的名字并且系统停止。我能够部分实现。但这里的问题是同时两个演员从他们的邻居那里得到消息并停止。例如,如果我从 1 开始进程,1 向 4 和 2,2 向 3 和 4 向 3 发送消息,所以理论上应该打印 3,但我会打印 2 和 3。请建议可以做什么。以下是我的示例逻辑。
object Main extends App {
//creating a actor system
val actorSystem = ActorSystem("System")
//creating four actor instances with id as 1,2,3,4
for (i <- 1 to 4) {
actorSystem.actorOf(CircularActor.props(4), "" + i)
}
//initiating message to actor 1
actorSystem.actorSelection(s"/user/1") ! "hello from x"
}
class CircularActor(n: Int) extends Actor {
//variable to keep a track whether the actor received two meesages(i.e.from both neighbours)
var noOfMessagesReceived = 0
//generic method to send message using actorPath
def messageNeighbour(path:String){
context.actorSelection(path) ! "hello from x"
}
override def receive: Receive = {
case "hello from x" =>
noOfMessagesReceived += 1
if (noOfMessagesReceived == 2) {
println(s"The actor that received both messages is ${self.path.name}")
context.system.terminate()
}
else {
//Figures out id of sender
val pathValue = sender().path.name
//Gets its own name
val ownId = self.path.name.toInt
//Finds out the previous neighbor
val prev = if (ownId - 1 == 0) n else ownId - 1
//Finds next neighbour
val next = if (ownId == n) 1 else ownId + 1
//If the message is from deadletter, then this is the initiator actor
if (pathValue == "deadLetters") {
messageNeighbour(s"/user/$prev")
messageNeighbour(s"/user/$next")
}
//If the message is from its next neighbour,send it to previous
else if (pathValue.toInt == next) {
//introducing random delay
Thread.sleep(1 + Random.nextInt(100))
messageNeighbour(s"/user/$prev")
}
//If none of above,then send it to previous.
else {
Thread.sleep(1 + Random.nextInt(100))
messageNeighbour(s"/user/$next")
}
}
}
object CircularActor {
def props(n: Int): Props = Props(new CircularActor(n))
}
【问题讨论】: