我有一个类,它本身就是一个演员:
class Client(server: Server, systemActor: ActorRef) extends Actor {
...
}
我有一个管理已连接客户端的列表。生成客户端 Actor 的 Actor 监视数据库中的“服务器”列表,并为每个服务器生成一个客户端连接,如下所示:
private val clientList = mutable.ArrayBuffer.empty[Client]
class RegistrationWatcherActor(val systemActor: ActorSystem) extends Actor with Timers {
implicit val system: ActorSystem = context.system
timers.startSingleTimer(TickKey, FirstTick, FiniteDuration(1, TimeUnit.SECONDS)) // wait 10 seconds to give database time to initiate
private def checkRegistrations(): Unit = {
val database = DatabaseUtil.getInstance
val serversOutgoing: Seq[Server] = database.getAll[Server](classOf[Server])
for (server <- serversOutgoing) {
val client = clientList.find{ client => client.server == server }
if (client.isEmpty) { // client for this server was not found, so create one
}
}
}
def receive: Receive = {
case FirstTick =>
timers.startTimerWithFixedDelay(TickKey, Tick, FiniteDuration(1, TimeUnit.SECONDS))
case Tick =>
checkRegistrations()
}
}
问题
在检查中,if (client.isEmpty)
我想创建一个实例Client
,将其作为参与者生成,并将引用放入列表中,这样它就不会再次被创建。如您所见,我确定客户端是否已创建的方法是将其serverID
与数据库中存储的客户端进行检查。
理想情况下,我想这样做:
val client = new Client(server, systemActor)
systemActor.actorOf(Props(client), server.serverID)
clientList.append(client)
请问有什么建议吗?
选择
我意识到我可以列出clientList
并将String
存储serverID
在这里。但是,我最终希望RegistrationWatcher
能够控制客户端的各个方面,因此Client
最好引用该对象。
作为一般原则,actor 模型的部分要点是,actor 是自主的。因此,希望 能够
RegistrationWatcherActor
“控制” 的行为Client
/状态,这表明 actor 的职责分解不正确。如果您确实需要在参与者之间(或参与者与外界之间)共享某些状态,请注意,参与者内的单线程幻觉正在被打破,您基本上回到了多线程并发的世界(例如,需要使用
synchronized
块、volatile
并发集合或原子):即使您引用了Client
,也无法真正保证从调用的方法在下次向发送消息并且该消息即将被处理Client
之前是可见的。在这种情况下,最好将共享状态包装在传递给的并将保存在中。RegistrationWatcherActor
RegistrationWatcherActor
Client
AtomicReference
Client
AtomicReference
RegistrationWatcherActor