JavaFX/ScalaFX アプリケーションで Akka アクターを実行するにはどうすればいいですか?
(これは最初の回答に基づいた質問の更新です)
解決策は同じ実行コンテキストを共有することですか? つまり、JavaFx ExecutorService に基づくアクターディスパッチャーを持つということですか? (UI 操作コードを実行するもの)
それは、1 つのエージェントが UI を表し、それを操作できることを意味しますか? つまり、以下で示唆されているように、複数のアクターが UI ExecutorService 上にある場合、エージェント間で状態を共有すること (オブジェクトは UI) を意味しませんか?
2 人のアクターは、異なるエグゼキュータ サービス上で通信できますか? この質問をしているのは、以下で示唆されていることから、一部のエージェントは UI エグゼキュータ サービス上にあり、他のエージェントはそうではないと考えられるためです。
最後に、Executor コンテキストが異なる akka をそのまま使用し、Platform.runLater を使用すると、UI のパフォーマンスに何らかの影響が出る可能性があるのはなぜでしょうか。これにより、同じアプリケーションで複数の executor サービスを使用することは悪いことなのかという疑問が生じます。
ベストアンサー1
- 先物
scala Futures を JavaFX などのシングルスレッド ツールキットと一緒に使用する最善の方法は、UI ツールキットのスレッドで Futures またはアクターを実行できるエグゼキュータを定義することです。
Swingにも同じ問題があり、Swingスレッドで更新を行う必要があります。Viktor Klangは次の解決策を思いつきました。スイング実行コンテキスト以下は 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 上で実行されている限り、futures のパイプラインは非常に複雑になる可能性があります。
注: ForkJoin ec をデフォルトにして JavaFX ec を明示的に渡すか、その逆を行うかはあなた次第です。エラーを防ぐために JavaFX ec をデフォルトにして、非同期で実行できる部分を ForkJoin ec で明示的にマークすることをお勧めします。
- 俳優
アクターベースのシステムをシングルスレッドUIツールキットと統合するためのソリューションもあります。スウィング俳優交換するだけです
SwingUtilities.invokeLater(command)
と
Platform.runLater(command)
これで準備完了です!
- いつ使うか
大きなUIアプリケーションがあり、非同期操作(ファイルの読み込みや計算の実行)を分離したいだけの場合は、フューチャーベースのアプローチがおそらく望ましいでしょう。ただし、どれでもデフォルトの実行コンテキストで非同期に実行される futures 内の JavaFX コンポーネントとの対話 (読み取りも書き込みもなし)。
大規模なアクター ベースのシステムがあり、一部の部分に UI をアタッチしたいだけの場合は、JavaFX スレッドで実行されるアクターをいくつか用意することが望ましいでしょう。結果は人によって異なります。