Чтобы ответить на ваши вопросы:
1) Способ изменения графического интерфейса в примере кода сохранить?
Да.
JavaFX , на котором сидит ScalaFX , обеспечивает безопасность потока, настаивая на том, чтобы все взаимодействия GUI происходили в потоке приложения JavaFX ( JAT ), который создается во время инициализации JavaFX ( ScalaFX позаботится об этом за вас).Любой код, работающий в другом потоке, который взаимодействует с JavaFX / ScalaFX , приведет к ошибке.
Вы гарантируете, что ваш код GUI выполняется на JAT путем передачи взаимодействующего кода с помощью метода Platform.runLater
, который оценивает свои аргументы в JAT .Поскольку аргументы передаются по имени , они не оцениваются в вызывающем потоке.
Итак, что касается JavaFX , ваш код является потокобезопасным.
Однако потенциальные проблемы могут возникать, если код, который вы передаете в Platform.runLater
, содержит какие-либо ссылки на изменяемое состояние, поддерживаемое в других потоках.
У вас есть два вызова Platform.runLater
.В первом из них (button.text = "0")
, единственное изменяемое состояние (button.text
) принадлежит JavaFX , которое будет проверено и изменено на JAT , так что вы хорошо.
Во втором вызове (button.text = n.toString
) вы передаете то же самое изменяемое состояние JavaFX (button.text
). Но вы также передаете ссылку на n
, который принадлежит потоку GUIActor
. Однако это значение равно неизменяемому , поэтому нет проблем с потоками при просмотре его значения. (Счет поддерживается Akka GUIActor
контекст класса, и единственные взаимодействия, которые изменяют количество, происходят через Akka механизм обработки сообщений, который гарантированно безопасен для потоков.)
Тем не менее, есть одинПотенциальная проблема здесь: Future
сбрасывает счетчик (который будет происходить в потоке GUIActor
), а также устанавливает текст в "0"
(который будет происходить в JAT ). Следовательно,возможно, что эти два действия произойдут в неожиданном порядке, например * 1Текст 074 * изменяется на "0"
до , счет фактически сбрасывается.Если это происходит одновременно с нажатием кнопки пользователем, вы получите условие гонки и возможно, что отображаемое значение может в конечном итоге не соответствовать текущему количеству.
2) Может быть, есть лучший способ сделать это?
Всегда есть лучший способ!; -)
Если честно, учитывая этот небольшой пример, дальнейших улучшений не так много.
Я бы постарался сохранить все взаимодействие с GUI. внутри либо GUIActor
, либо объекта Main
для упрощения потоков и синхронизации.
Например, вместо возврата к Future
, вернитесь к последней точке в предыдущем ответе.обновите button.text
, было бы лучше, если бы это было сделано как часть обработчика сообщений CounterReset
в GUIActor
, который затем гарантирует, что счетчик и внешний вид button
синхронизированы правильно (или, по крайней мере, они 'всегда обновляется в одном и том же порядке), причем отображаемое значение гарантированно соответствует количеству.
Если ваш класс GUIActor
обрабатывает много взаимодействий с GUI , то вы можетепусть он выполнит весь свой код на JAT (я думаю, что это было целью примера Виктора Кланга), что упростило бы большую часть его кода.Например, вам не нужно было бы вызывать Platform.runLater
для взаимодействия с GUI .Недостатком является то, что вы не сможете выполнять обработку параллельно с GUI , что может снизить его производительность и быстродействие в результате.
3) Можно ли запускать разные потокиот того же диспетчера?(если да, то как?)
Вы можете указать пользовательские контексты исполнения для фьючерсов и Akka актеров, чтобы лучше контролировать свои потоки и диспетчеризацию. Однако, учитывая наблюдение Дональда Кнута о том, что «преждевременная оптимизация является корнем всего зла», нет никаких доказательств того, что это даст вам какие-либо преимущества, и в результате ваш код станет значительно более сложным.
Насколько я знаю, вы не можете изменить контекст выполнения для JavaFX / ScalaFX , поскольку создание JAT должно точно контролироваться в Чтобы гарантировать безопасность ниток. Но я могу ошибаться.
В любом случае накладные расходы, связанные с наличием разных диспетчеров, не будут высокими. Одна из причин использования фьючерсов и актеров заключается в том, что они позаботятся об этих проблемах по умолчанию. Если у вас нет веских причин поступить иначе, я бы использовал значения по умолчанию.