2013-05-11 5 views
1

Мое приложение имеет класс ApplicationUsers, который не имеет изменяемых элементов. После создания экземпляров он считывает всю пользовательскую базу данных (относительно небольшую) в неизменяемую коллекцию. Он имеет несколько методов для запроса данных.Можно ли безопасно разделить var?

Теперь я столкнулся с проблемой создания новых пользователей (или изменения некоторых их атрибутов). Моя текущая идея заключается в том, чтобы использовать актер Akka, что на высоком уровне, будет выглядеть следующим образом:

class UserActor extends Actor{ 
    var users = new ApplicationUsers 

    def receive = { 
    case GetUsers => sender ! users 

    case SomeMutableOperation => { 
     PerformTheChangeOnTheDatabase() // does not alter users (which is immutable) 
     users = new ApplicationUsers // reads the database from scratch into a new immutable instance 
    } 
    } 
} 

Является ли это безопасно? Мое рассуждение заключается в том, что оно должно быть: всякий раз, когда users изменен на SomeMutableOperation, любые другие темы, использующие предыдущие экземпляры users, уже имеют дескриптор старой версии и не должны быть затронуты. Кроме того, любой запрос GetUsers не будет действовать, пока новый экземпляр не будет безопасно построен.

Есть ли что-нибудь, что мне не хватает? Является ли моя конструкция безопасной?

ОБНОВЛЕНИЕ: Я, вероятно, должен использовать Agents, но вопрос по-прежнему сохраняется: безопасен ли выше?

ответ

3

Вы делаете это точно: имеете неизменные типы данных и ссылаетесь на них через var внутри актера. Таким образом, вы можете свободно делиться данными, а изменчивость ограничивается актером. Единственное, на что нужно обратить внимание, - это ссылка на var из укупорочного средства, которое выполняется вне актера (например, в трансформации Future или Props). В таком случае вам нужно сделать стек локальной копии:

val currentUsers = users 
other ? Process(users) recoverWith { case _ => backup ? Process(currentUsers) } 

В первом случае вы просто захватить значение, которое является точной, но попросив backup происходит из другого потока, следовательно, необходимость для val currentUsers.

1

Выглядит хорошо. Вам, кажется, не нужны Агенты.

+0

Спасибо. Я думаю, что агенты упростили бы мой код (не нужно было бы создавать вышеупомянутую конструкцию), а также естественно отделяли бы обновление базы данных от обновления объекта 'users', что в моем случае было бы лучшим дизайном. – Eduardo

+0

Я думаю, что проблема с агентами в том, что они только локальны для узла (jvm), который вы используете. Вы не можете передавать их удаленно на другие узлы. Это может вызвать проблемы, когда вы хотите масштабировать свою систему. – Bacon

Смежные вопросы