問題タブ [event-dispatch-thread]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - イベントディスパッチスレッドに変数を渡す
EDT を使用して GUI を更新する必要があるため、GUI がロックしますが、GUI で更新中の変数も渡す必要があります。
これは動作しません。EDT にテキストを設定する必要がありますが、numOfPlayers を final として宣言せずに渡すことはできません (新しいプレイヤーがサーバーに参加すると変更されるため、これはしたくありません)。
java - EDT とメイン スレッド間の通信
私は最近取り組んでいるプロジェクトについて多くの質問をしています。これが私がいるシナリオであり、正しい方向への助けや指摘は大いに役立ちます...
これは、サーバーと複数のクライアントで構築されたネットワーク プログラムです。各クライアントには、サーバーから送信されたコマンドに従って動作する必要がある GUI があります。各クライアントは、 と呼ばれるクラス内にラップされますPlayer
。これPlayer
には GUI (extends JFrame
) と main メソッドがあり、サーバーには main メソッドのみ (GUI なし) があります。最初に、このクラスは次のようにメイン スレッドで作成されました。
クラス全体Player
が EDT で実行されていることに気付くまで、これは正常に機能していました。そのため、サーバーからのコマンドを待つと、そのコマンドが送信されて適切なアクションが実行されるまで、GUI 全体がロックされます。ご想像のとおり、これは恐ろしい設計であり、何かをチェックしたいときはいつでも、GUI が損なわれないように、クレイジーな回避策を見つけなければならないというコーディング環境の本当の苦痛であることが証明されました。
明らかに、別のスレッドでサーバーからのコマンドを確認し、EDT で GUI コンポーネントを実行する必要があります。私の 2 番目の実装には 2 つのクラスがありました。1 つは GUI 用で、もう 1 つはPlayer
. アイデアは、次のようなクラスPlayer
から GUI にアクセスできるように、GUI を保持する変数を持っているというものでした。Player
this
新しいオブジェクトの内部は.ではなくRunnable
オブジェクトを参照するため、これも機能しません。Runnable
Player
Player
1 つのスレッド内のクラスと EDT スレッド内の対応する GUI クラスとの間で通信するにはどうすればよいですか?
java - バックグラウンド タスク中に Swing GUI がロックするのを防ぐ
オブジェクトのリストを格納するスイング アプリケーションがあります。ユーザーがボタンをクリックすると、
リスト内の各オブジェクトに対して 2 つの操作を実行し、それが完了したら、JPanel で結果をグラフ化します。SwingWorker、Callable、Runnable で処理を試みましたが、何をしても、リストの処理中に (IO バウンドであるため、最大で数分かかる場合があります)、GUI がロックされます。
おそらくスレッドか何かを呼び出す方法だと思いますか、それともグラフ機能に関係している可能性がありますか? 非常に高速であるため、スレッド化されていません。
2 つの処理段階も順番に実行する必要があるため、2 番目の段階が最初の段階で確実に待機するようにする最善の方法は何ですか? join() を使用してから、
これを確実にしようとしていますが、これが私の問題の原因でもあるのではないかと心配しています.
私はどこでもいくつかのポインタを探してきましたが、何も見つからないので、ここで愚かなことをしていると確信しています.
java - EDT に直面してゲームの状態を管理する方法は?
Java プラットフォームでリアルタイム戦略ゲームのクローンを開発しています。ゲームの状態をどこに配置し、どのように管理するかについて、概念的な質問があります。ゲームはレンダリングとして Swing/Java2D を使用します。現在の開発段階では、シミュレーションも AI も存在せず、ユーザーだけがゲームの状態を変更できます (たとえば、建物の建設/解体、生産ラインの追加と削除、フリートと機器の組み立て)。したがって、ゲーム状態の操作は、レンダリング ルックアップなしでイベント ディスパッチ スレッドで実行できます。ゲームの状態は、さまざまな集計情報をユーザーに表示するためにも使用されます。
ただし、シミュレーションを導入する必要があるため (たとえば、建物の進行状況、人口の変化、艦隊の移動、製造プロセスなど)、タイマーと EDT でゲームの状態を変更すると、レンダリングが確実に遅くなります。
シミュレーション/AI 操作が 500 ミリ秒ごとに実行され、約 250 ミリ秒の長さの計算に SwingWorker を使用するとします。シミュレーションと可能なユーザー操作の間で、ゲームの状態の読み取りに関する競合状態がないことを確認するにはどうすればよいですか?
シミュレーションの結果 (少量のデータ) は、SwingUtilities.invokeLater() 呼び出しを介して効率的に EDT に戻すことができます。
ゲーム状態モデルは複雑すぎて、どこでも不変の値クラスを使用するだけでは実行不可能なようです。
この読み取り競合状態を解消するための比較的正しいアプローチはありますか? おそらく、すべてのタイマーティックで完全/部分的なゲーム状態のクローンを作成するか、ゲーム状態の生活空間を EDT から他のスレッドに変更しますか?
更新: (私が与えたコメントから) ゲームは 13 人の AI 制御のプレイヤー、1 人の人間のプレイヤーで動作し、約 10000 のゲーム オブジェクト (惑星、建物、装備、研究など) があります。たとえば、ゲーム オブジェクトには次の属性があります。
あるシナリオでは、ユーザーがこの惑星に新しい建物を建設します。これは、マップと建物のコレクションを変更する必要があるため、EDT で実行されます。これと並行して、シミュレーションが 500 ミリ秒ごとに実行され、すべてのゲーム惑星の建物へのエネルギー割り当てが計算されます。これは、統計収集のために建物コレクションをトラバースする必要があります。割り当てが計算されると、EDT に送信され、各建物のエネルギー フィールドが割り当てられます。
いずれにせよ、AI 計算の結果が EDT の構造に適用されるため、このプロパティを持つのは人間のプレイヤー インタラクションだけです。
一般に、オブジェクト属性の 75% は静的であり、レンダリングのみに使用されます。残りの部分は、ユーザーの操作またはシミュレーション/AI の決定によって変更できます。また、前のシミュレーション/AI ステップがすべての変更を書き戻すまで、新しいシミュレーション/AI ステップが開始されないことも保証されます。
私の目標は次のとおりです。
- ユーザー インタラクションを遅らせないようにします。たとえば、ユーザーが建物を惑星に配置し、0.5 秒後に視覚的なフィードバックを取得します。
- 計算、ロック待機などで EDT をブロックしないようにします。
- コレクションのトラバーサルと変更、属性の変更による同時実行の問題を回避する
オプション:
- きめ細かいオブジェクトのロック
- 不変コレクション
- 揮発性フィールド
- 部分的なスナップショット
これらはすべて、モデルとゲームに長所、短所、および原因があります。
更新 2:私はこのゲームについて話しています。私のクローンはここにあります。スクリーンショットは、レンダリングとデータ モデルの相互作用を想像するのに役立つ場合があります。
更新 3:
コメントから誤解されているように見えるので、問題を明確にするために小さなコードサンプルを提供しようとします。
したがって、オーバーラップは onAddBuildingClicked() と distributedPower() の間です。ここで、ゲーム モデルのさまざまな部分の間にこの種のオーバーラップが 50 ある場合を想像してください。
java - EDT の外部から Swing コンポーネントから値を取得する
私の現在のコードは次のようになります。
final 配列の使用は、ちょっとしたハックのように思えます。よりエレガントなソリューションはありますか?
私は多くの検索を行いましたが、これを行うための何かを見つけることができないようです.これは私を驚かせます. に出くわしSwingWorker
ますが、この場合に適しているかどうかわかりませんか?
JTextArea.getText()
それはスレッドセーフではないと思います。
ありがとう。
java - Java:SwingUtilities.invokeNowOrLaterIfEDT(...)などはありますか?
(以下の編集を必ずお読みください。この質問は明らかに混乱を招きます。申し訳ありません)
典型的なSwingUtilities.invokeLater
呼び出しは次のとおりです。
今、私は何になるかを知りたいSwingUtilities.invokeNowOrLaterIfEDT
です。
もちろん、次のような独自のユーティリティクラスを使用することもできます。
ただし、これには、EDTから呼び出されるたびに新しいスレッドが作成されるという欠点があります(そして、その新しいスレッドがスケジュールされるのを待つ必要があります)。
これを行う別の方法は、アプリのライフサイクル中に実行されている1つの追加スレッド(遅延インスタンス化される可能性があります)を使用して、ブロッキングキューを使用してをエンキューすることRunnables
です。利点は、EDTからそのようなメソッドを呼び出すたびにスレッドが常に作成されるとは限らないことです。
このようなものがデフォルトのJavaAPIに存在しますか?
上記の例のように、EDTから呼び出されるたびに新しいスレッドを作成するかRunnables
、EDTの外部で実行されるスレッドを1つ追加するだけで、キューに入れられますか?
編集:EDTから呼び出される場合と呼び出されない場合と同様SwingUtilities.invokeLater
に、私が考えていたメソッドはEDTから呼び出される場合と呼び出されない場合があります。GUI / EDTでのユーザーアクションからトリガーされる場合とされない場合がある、完全に非同期の何かを実行することです。SwingUtilities.invokeLater
EDTを使用しているかどうかに関係なく、EDTを呼び出すときに気にせずに、EDTで何かを実行できると非常に便利だと思います。invokeNowOrLaterIfEDT(...)
そして、上で示したものはとても便利だと思います。しかし、私はそれについて誤解されているかもしれません。そのような方法の必要性は狂っていますか?今、私は疑い始めています!?
編集2:私はまったくはっきりしていません、そして私はそれを理解します、それについて申し訳ありません。EDTからではなく非同期で実行したいのは、非常に長いプロセスではなく、プログレスバーや何が起こっているかを示すものなどの更新は必要ありません。シングルスレッド/キューに入れられている場合も問題ありません(明らかに、質問で述べました)。さまざまなコアなどに負荷を効率的に分散するためのスレッドプールをまったく求めていません。これらはEDTで実行する必要がなく、EDTから呼び出されるかどうかに関係なく、小さな計算であるだけです。これは、EDTの外部で実行したい非常に小さな非同期のものです。それらがすべて同じスレッドなどでキューに入れられている場合は問題ではありません。
しかし今、あなたの答えのおかげで、そのようなものが単一のスレッドと実行可能なキューを使用して実装された場合、長い計算のためにそのようなユーティリティメソッドを呼び出すことによって足で自分自身を撃つことは非常に簡単であることもわかりますその後、正しくマルチスレッド化されるのではなく、すべてがキューに入れられます。
java - invokeAndWait を使用して Swing から値を返す
私は次のアプローチを使用してコンポーネントを作成し、Swing から EDT の外部へ/から値を返します。たとえば、次のメソッドは を拡張してJFrame
、 を作成し、JPanel
それを親に追加できJFrame
ます。
Runnable
ローカルの長さ 1 の配列は、EDT で呼び出される内から「結果」を転送するために使用されます。まあ、それは「少し」ハックに見えるので、私の質問:
- これは理にかなっていますか?他の誰かがこのようなことをしていますか?
- 長さ 1 の配列は、結果を転送する良い方法ですか?
- これを行う簡単な方法はありますか?
java - EDT から非 EDT (イベント ディスパッチ スレッド) スレッドでスレッドを実行する
EDT で実行されているメソッドがあり、その中で新しい (EDT 以外の) スレッドで何かを実行させたいと考えています。私の現在のコードは次のとおりです。
java - イベント ディスパッチ スレッドの処理
「イベント発送スレッド」について質問があります。JFrameでもあるメインクラスがあります。コード内の残りのコンポーネントを初期化します。それらの一部は Swing を使用せず、一部は使用します。このようにEDTを使用してメインクラスを初期化するだけで十分ですか?...
このようにして、すべてが Event Dispatcher スレッドで実行されます。