Los actores de Scala como colas de un solo hilo.
-
05-07-2019 - |
Pregunta
Me gustaría usar actores en un programa donde tenga algún tipo de restricción en cuanto a tratar a algunos de los actores como si fueran colas. Por ejemplo, supongamos que tengo algún sistema externo al que se aplican los eventos de cambio y también algo de memoria caché de los datos del sistema externo. Así que tengo 2 actores:
ChangeApplicationActor
CacheActor
Como parte del ChangeApplicationActor
, cuando aplico un cambio a alguna entidad X
en el sistema externo, deseo enviar algún evento para indicar al CacheActor
para sincronizar:
val changeApplicationActor = actor {
loop {
react {
case ChangeInstruction(x) =>
externalSystem.applyChange(x)
cacheActor ! Sync(x)
}
}
}
Pero ahora tengo dos requisitos:
- El
CacheActor
tiene un estado interno y, idealmente, me gustaría que procesara sus instrucciones deSync
de forma secuencial - Si termino con la bandeja de entrada de
CacheActor
que contiene dos instruccionesSync (x)
para el mismo valor dex
, entonces me gustaría ignorar la segunda (es decir, solo debería tener una instrucción pendiente deSync
para cualquier valor dado dex
)
¿Hay alguna forma de forzar a un actor a ser de un solo hilo? ¿Hay alguna manera de acceder al buzón del actor y eliminar cualquier evento duplicado? ¿No puedo evitar implementar el CacheActor
como, um, no es un Actor ?
Solución
Se garantiza que un actor solo se ejecuta en un hilo a la vez, y los mensajes en el buzón del actor están en orden FIFO, por lo que el # 1 está ahí.
2 es más complicado ya que no hay soporte integrado para él. Hay un atributo en el actor llamado "buzón". Puede acceder al buzón directamente en lugar de recibir o reaccionar. Todo lo que tiene que hacer es extraer los mensajes de sincronización correspondientes del buzón antes de que termine de procesar el mensaje. Al hacer esto, debe sincronizar con el actor para evitar que otro hilo intente agregar cosas al buzón durante el envío de un mensaje.
Cabe señalar que la sincronización en el actor elimina las garantías de libertad de bloqueo hechas por la biblioteca y reducirá la escalabilidad. Pero desde un punto de vista práctico, probablemente esté bien.