4

このコードがSwingアプリケーションをフリーズさせるのはなぜですか?Swingコンポーネントは、私のInfiniteLoopスレッドとは別のスレッドにあります。各印刷の前にrun()メソッドにスリープを導入すると、プログラムは正常に機能します。誰か手がかりはありますか?

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI(); // <-- creates the swing frame and component
        }
    });

    Thread t = new Thread(new InfiniteLoop()); 
    t.start();
}

public class InfiniteLoop implements Runnable
{
    private static Logger logger = Logger.getLogger(InfiniteLoop.class);
    public void run()
    {
         while(true)
         {
              log.info("test");
         }
    }
}
4

1 に答える 1

3

ここでの答えは、Java のスレッド スケジューリングの実装 (または、プラットフォームの Java スレッド スケジューリングの実装の詳細) に関係しています。ほとんどの Java スレッド化実装は、スレッドが待機状態になるまで、特定のスレッドを (特定の優先度レベルで) 実行することになります。次に、その優先度レベルの次のスレッドが実行されます。JVM 仕様では正確な動作が指定されていないことに注意してください。これは、JVM 実装者が決定します。

ワーカー スレッドにスリープを挿入する代わりに、ワーカーの優先度を下げることを検討することをお勧めします。スレッドをスリープ状態にすることはできますが、それを覚えておくのは面倒です。また、ワーカー スレッドが他の方法で行う必要があるよりも、処理に時間がかかるようになります。スリープ呼び出しを挿入してしまった場合は、0 ミリ秒間実行してください (スレッドを解放するには十分ですが、アクティブなスレッドが他にない場合はすぐに実行に戻る必要があります)。

これについて少し説明している記事があります。

潜在的な改良点として: バックグラウンド スレッドがすべての CPU を使用しているため、invokeLater() 呼び出しは、ランナブルをデキューする機会のないキューに配置してしまう可能性があります。興味深い実験として、バックグラウンド スレッドの起動を Runnable に移動することが考えられます。これにより、バックグラウンド スレッドが CPU を消費し始める前に EDT を初期化する機会が得られます。

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI(); // <-- creates the swing frame and component

            Thread t = new Thread(new InfiniteLoop()); 
            t.start();
        }
    });

}

あるいは:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            Thread t = new Thread(new InfiniteLoop()); 
            t.start();

            createAndShowGUI(); // <-- creates the swing frame and component
        }
    });

}

私は実際にこれの結果に興味があります(ただし、実際にテストするほど興味はありません:-))。私がオンラインで見た参考文献の中には、デフォルトで EDT がより高い優先度レベルで実行されると書かれているものがあります (この場合、EDT 自体が枯渇することはありません)。EDT 内からバックグラウンド スレッドを開始した場合、Swing インターフェイスは応答性を維持しますか?

于 2012-06-01T04:04:30.693 に答える