Ответ 1
- Фьючерс
Лучший способ использовать scala Фьючерсы вместе с однопоточным инструментарием, таким как JavaFX, состоят в том, чтобы определить исполнителя, который позволяет выполнять фьючерсы или актеры в потоке инструментария пользовательского интерфейса.
Та же проблема существует и для Swing, которая также требует обновления обновлений для потока swing. Виктор Кланг придумал следующее решение Контекст качания Swing. Здесь он переводится для JavaFX:
import akka.dispatch.ExecutionContext
import javafx.application.Platform
import java.util.concurrent.Executor
//
object JavaFXExecutionContext {
implicit val javaFxExecutionContext: ExecutionContext = ExecutionContext.fromExecutor(new Executor {
def execute(command: Runnable): Unit = Platform.runLater(command)
})
}
Вы бы использовали его следующим образом:
// import the default ec
import scala.concurrent.ExecutionContext.Implicits.global
// define the JavaFX ec so we can use it explicitly
val fxec = JavaFXExecutionContext.javaFxExecutionContext
future {
// some asynchronous computation, running on the default
// ForkJoin ExecutionContext because no ec is passed
// explicitly
}.map(result => {
// update JavaFX components from result
// This will run in the JavaFX thread.
// Check Platform.isFxApplicationThread() to be sure!
})(fxec)
Конвейер фьючерсов может быть очень сложным, если шаги (шаги), которые взаимодействуют с компонентами JavaFX, все запущены в JavaFX ExecutionContext.
Примечание. Это зависит от вас, внесите ли вы значение ForkJoin ec по умолчанию и передайте JavaFX ec явно или наоборот. Возможно, было бы неплохо сделать JavaFX ec по умолчанию для предотвращения ошибок и отметить части, которые могут выполняться асинхронно с помощью ForkJoin ec.
- Актеры
Для интеграции системы на основе актера с однопоточным инструментарием пользовательского интерфейса существует также решение. Смотрите Свинг-актеры. Все, что вам нужно сделать, это заменить
SwingUtilities.invokeLater(command)
с
Platform.runLater(command)
и вам хорошо идти!
- Когда использовать
Если у вас есть большое приложение пользовательского интерфейса и вы хотите просто отключить некоторые асинхронные операции (загрузка файла или выполнение некоторых вычислений), вероятно, предпочтителен подход на основе фьючерсов. Но будьте осторожны, чтобы не взаимодействовать (ни читать, ни писать) с компонентами JavaFX во фьючерсах, которые выполняются асинхронно в контексте выполнения по умолчанию.
Если у вас есть большая система на основе актеров и вы просто хотите подключить пользовательский интерфейс к некоторым частям, возможно, несколько предпочтительных участников, работающих по потоку JavaFX. YMMV.