11

オブジェクトのリストを格納するスイング アプリケーションがあります。ユーザーがボタンをクリックすると、

リスト内の各オブジェクトに対して 2 つの操作を実行し、それが完了したら、JPanel で結果をグラフ化します。SwingWorker、Callable、Runnable で処理を試みましたが、何をしても、リストの処理中に (IO バウンドであるため、最大で数分かかる場合があります)、GUI がロックされます。

おそらくスレッドか何かを呼び出す方法だと思いますか、それともグラフ機能に関係している可能性がありますか? 非常に高速であるため、スレッド化されていません。

2 つの処理段階も順番に実行する必要があるため、2 番目の段階が最初の段階で確実に待機するようにする最善の方法は何ですか? join() を使用してから、

while(x.isAlive())  
{  
        Thread.sleep(1000);  
}

これを確実にしようとしていますが、これが私の問題の原因でもあるのではないかと心配しています.

私はどこでもいくつかのポインタを探してきましたが、何も見つからないので、ここで愚かなことをしていると確信しています.

4

5 に答える 5

19

問題は、実行時間の長いタスクが、GUI の応答性を維持するスレッドをブロックしていることです。

あなたがする必要があるのは、長時間実行されるタスクを別のスレッドに置くことです。

これを行う一般的な方法として、タイマーまたはSwingWorker.

Java チュートリアルには、並行処理のレッスンで、これらのことに関する多くの情報があります。

最初のタスクが 2 番目のタスクの前に終了するようにするには、両方を同じスレッドに配置します。そうすれば、2 つの異なるスレッドのタイミングを正しく維持することを心配する必要がなくなります。

あなたの場合の SwingWorkerFor のサンプル実装は次のとおりです。

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
    private List<Object> list
    public YourClassSwingWorker(List<Object> theOriginalList){
        list = theOriginalList;
    }

    @Override
    public List<Object> doInBackground() {
        // Do the first opperation on the list
        // Do the second opperation on the list

        return list;
    }

    @Override
    public void done() {
        // Update the GUI with the updated list.
    }
}

このコードを使用するには、リストを変更するイベントが発生したときに、新しいSwingWorkerを作成して開始するように指示します。

于 2009-06-02T17:49:00.393 に答える
7

スイングスレッドが正しく戻されていません。呼び出し可能/実行可能を使用していることはわかっていますが、正しく実行していないと思います(ただし、確実に知るのに十分なコードを投稿していません)。

基本的な構造は次のとおりです。

swingMethod() { // Okay, this is a button callback, we now own the swing thread
    Thread t=new Thread(new ActuallyDoStuff());
    t.start();
}

public class ActuallyDoStuff() implements Runnable {
    public void run() {
        // this is where you actually do the work
    }
}

これは頭​​から離れていますが、thread.startを実行しておらず、代わりにrunメソッドを直接呼び出しているか、最初のメソッドで何か他のことを実行してロックしていると推測しています( thread.joinのように)。これらのどちらもスイングスレッドを解放しません。最初のメソッドはすぐに戻らなければなりません。run()メソッドは必要なだけ長くかかる可能性があります。

最初のメソッドでthread.joinを実行している場合、スレッドはシステムに返されません。

編集:(実際には2番目の編集)私はあなたが実際に感じている問題について話すと思います-モデル/ビュー/コントローラーシステムの観点からもっと考えたいと思うかもしれません。作成しているコードはコントローラーです(ビューは通常、画面上のコンポーネントと見なされます。ビュー/コントローラーは通常、非常に緊密にバインドされています)。

コントローラがイベントを取得すると、作業をモデルに渡す必要があります。その場合、ビューは画像から外れます。モデルを待つのではなく、完了しただけです。

モデルが完成したら、コントローラーに何か他のことをするように指示する必要があります。これは、invokeメソッドの1つを介して行われます。これにより、制御がコントローラーに戻され、陽気な道を進みます。このように考えると、コントロールを分離して意図的に前後に渡すことはそれほどかさばることはなく、実際にはこのようにすることは非常に一般的です。

于 2009-06-02T18:18:09.830 に答える
1

GUIスレッド内からスレッドが終了するのを待っていることが問題のようです。GUIスレッドはこれらのスレッドを待機するべきではありません。代わりに、ワーカースレッドにフラグを設定するGUIスレッド上のメソッドを呼び出させる必要があります。両方のフラグが設定されると、両方のスレッドが終了したことがわかり、グラフを作成できます。

于 2009-06-02T18:26:14.043 に答える
0

私は実際にスイングスレッドモデルについて話すことはできませんが、:

2 つの処理段階も順番に実行する必要があるため、2 番目の段階が最初の段階で確実に待機するようにする最善の方法は何ですか?

この種の機能については、2 つのワーカー スレッドを作成し、JMS ブローカーを埋め込むことをお勧めします。読み取り元の JMS キューにメッセージを渡すことで、2 つのスレッドに作業を配信します。GUI スレッドはキューを自由に調べて、いつ作業が行われているかを判断し、UI でプレイの状態を表します。

于 2009-06-02T18:53:09.033 に答える
0

私の問題の解決策は、jjnguy と Bill K の回答を組み合わせることでした。次のように、SwingWorker 内でスレッドを使用する必要がありました。

public class Worker extends SwingWorker<Void, Void>   
{  
    private List<Object> list;  
    public YourClassSwingWorker(List<Object> theOriginalList){  
        list = theOriginalList;  
    }

    @Override
    public List<Object> doInBackground() {
        Thread t = new Thread(new ProcessorThread(list));  
        t.start();
    }

    @Override
    public void done() {
        // draw graph on GUI
    }
}  
class ProcessorThread implements Runnable {  
    //do lots of IO stuff  
    Thread t2 = new Thread(new SecondProcess());
    t2.start();  
}

これにより、すべての作業が GUI から離れたワーカー スレッドによって行われるようになり、SwingWorker 自体がすべての作業を行っていないことが保証されました。これは問題であった可能性があります。

于 2009-06-03T23:22:45.003 に答える