Актеры Scala как однопоточные очереди
-
05-07-2019 - |
Вопрос
Я хотел бы использовать актеров в программе, где у меня будет какое-то ограничение, относящееся к тому, чтобы рассматривать некоторых актеров, как будто они были очередями. Например, предположим, у меня есть какая-то внешняя система, к которой применяются события изменений, а также некоторый кеш данных внешней системы. Итак, у меня есть 2 актера:
<Ол> Как часть ChangeApplicationActor
, когда я применяю изменение к некоторому объекту X
во внешней системе, я хочу отправить некоторое событие, чтобы сообщить CacheActor
для синхронизации:
val changeApplicationActor = actor {
loop {
react {
case ChangeInstruction(x) =>
externalSystem.applyChange(x)
cacheActor ! Sync(x)
}
}
}
Но теперь у меня есть два требования:
<Ол> CacheActor
имеет внутреннее состояние, и в идеале я бы хотел, чтобы он последовательно обрабатывал свои инструкции Sync
CacheActor
, содержащие две инструкции Sync (x)
для одного и того же значения x
, то я хотелось бы проигнорировать вторую (т.е. у меня должна быть только одна ожидающая инструкция Sync
для любого заданного значения x
) Есть ли способ заставить актера быть однопоточным? Есть ли способ получить доступ к почтовому ящику актера и удалить дубликаты событий? Могу ли я не избежать реализации CacheActor
, поскольку не Actor ?
Решение
Актер гарантированно исполняется только в одном потоке за раз, а сообщения в почтовом ящике актера располагаются в порядке FIFO, поэтому # 1 там.
2 сложнее, поскольку для него нет встроенной поддержки. У актера есть атрибут, называемый «почтовый ящик». Вы можете получить доступ к почтовому ящику напрямую, а не через получение или реагирование. Все, что вам нужно сделать, это вытащить вызов соответствующих сообщений синхронизации из почтового ящика, прежде чем вы закончите обработку сообщения. При этом необходимо выполнить синхронизацию на актере, чтобы другой поток не пытался добавить материал в почтовый ящик во время отправки сообщения.
Следует отметить, что синхронизация на актере устраняет гарантии свободы взаимоблокировок, предоставляемые библиотекой, и снижает масштабируемость. Но с практической точки зрения вы, вероятно, будете в порядке.