4

私が持っているプログラムは、物理シミュレーションを(基本的に)視覚化します。現時点では動作しますが、非常に応答しなくなる可能性があります。その理由はわかっていると思います。イベント スレッドで実行される (read:all) 計算が多すぎます。

「再生」ボタンが押されると、Timer定期的に起動して呼び出す Swing が作成されupdateTime()ます。問題は、updateTime()すべての時間依存オブジェクトを繰り返し処理し、適切な量 (実際の経過時間、またはティックごとの任意の時間単位) だけ時間をかけて伝播するように指示することです。これらの計算とその後の GUI の更新はすべて、イベント ディスパッチ スレッド上で行われます。

したがって、この計算をできるだけオフロードしたいと思います。s が最適だと思いますSwingWorkerが、それらを既存のコードに組み込む方法がわかりません。SwingWorkerそれらの多くはすでに他のクラスを拡張しているため、既存のクラスを拡張することはできません。

これまでの私の最善のアイデアは、実装する時間依存オブジェクトごとにインターフェイスを作成することです。インターフェイスは 2 つのメソッドを指定calcUpdateTime()しますdrawUpdateTime()。現在の各updateTime()方法を、物理計算 ( にcalc_) と GUI の更新 ( にdraw_) に分割します。TimeDependant次に、コンストラクターでオブジェクトを受け取る SwingWorker のクラスを 1 つだけ作成し、それdoInBackgroundが を呼び出しcalcUpdateTimedoneを呼び出しますdrawUpdateTime。それで、私はすべての出現を置き換えることができます

myObj.updateTime(currentTime);

new MySwingWorker(myObj, currentTime).execute();

私はこのアイデアを SO で実行したかったのです。なぜなら、それは正しくないと感じたからです。プロジェクト全体をリファクタリングして、私が悪いアイデアから始めたことを知りたくないからです。MySwingWorkerまた、ティックごとに潜在的に数十の s を作成するのはおそらく悪い考えではありませんか?

ここまで読んでくれてありがとう。

4

2 に答える 2

2

SwingWorker.execute()そうです、本当に必要のない多くのスレッドを作成して破棄することになるので、ティックごとにすべてのワーカーを呼び出す必要はありません。

ただし、バックグラウンドで実行する必要のあるコード(の実装)をSwingで実行して後でGUIを更新する必要のあるコードからSwingWorker簡単に分離できるため、aを使用することをお勧めします。SwingWorker.doInBackground()(の実装SwingWorker.done())。

javax.swing.Timerまたはを使用するのではなく、を使用java.util.Timerすることをお勧めしjava.util.concurrent.ScheduledThreadPoolExecutorます。基本的にjava.util.Timer、バックグラウンドで動作しているスレッドの数、バックグラウンドスレッドでスローされた例外の処理方法などを制御する機会を提供することを除いて、できることはすべて実行できます。

于 2010-02-20T21:43:27.297 に答える
0

Swingタイマーを使用して(パフォーマンスに関して)悪い経験をしました。Swing 全体のすべてのイベントが同じスレッドを使用するため、予期しない遅延がかなり発生するようです。

また、1 ティックごとに複数の Swing ワーカー インスタンスが存在することについては、自分の直感を信じることをお勧めします。(SwingWorkerドキュメントによると、一度だけ実行するように設計されているため、必ずしも安全に再利用できるとは限りません)。

あなたが必要とすることをするかもしれないタイマーはjava.util.Timer. これには、タイムアウトを指定するための非常に多くのオプションがありますが、タイミング シミュレーションの忠実度によっては、これでも適切ではない場合があります。(例: リアルタイムで実行したいが、実際にはリアルタイムよりも計算に時間がかかる場合、どうすればよいでしょうか? ゆっくり実行するか、時間ステップをスキップし始めるか?)

したがって、あなたの calc/draw ルーチンが何を含んでいるのか正確にはわからないので、試してみることを暫定的にお勧めしjava.util.Timerます。有効期限が切れたら (「リアルタイム乗数」に基づいて適切と思われるタイムアウト期間の後)、すべての計算を実行し、結果を EDT スレッドに戻して描画を行います (たとえば、それらをSwingUtilities.invokeLater())。

もちろん、EDT が計算スレッドと同じオブジェクトを参照する場合は、ロックの問題が発生する可能性があります。理想的には、計算スレッドが不変の結果を EDT に渡すことができれば、ロックを導入する必要がなくなります。

(免責事項:上記のいずれも、GUI用と計算用を除いて、複数のコア/プロセッサを実際に考慮していません。アプリケーションを並列化したい場合、それはおそらく適切な解決策ではありません).

于 2010-02-18T10:48:43.090 に答える