8

SwingWorkerあまり使っていないので色々と試してみたかったのです。代わりに、問題が発生し、何が問題なのかわかりません。

この問題を示す短いSSCCEを次に示します (SSCCE が好きな人は知っています)。

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class SwingWorkerTest
{
    public static void main (String[] args)
    {
        SwingUtilities.invokeLater (new Runnable ()
        {
            @Override
            public void run ()
            {
                new MySwingWorker (500).execute ();
                new MySwingWorker (900).execute ();
                new MySwingWorker (1200).execute ();
            }
        });
    }
}

class MySwingWorker extends SwingWorker<Void, Void>
{
    private int ms;

    public MySwingWorker (int ms)
    {
        this.ms = ms;
    }

    @Override
    protected Void doInBackground()
    {
        Thread t = Thread.currentThread ();

        for (int i = 0; i < 50; i++)
        {
            try
            {
                Thread.sleep (ms);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace ();
            }

            System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName () + " (" + t.getId () + ")");
        }

        return null;
    }
}

したがって、私のプログラムは、画面に行を出力し、指定されたミリ秒数の間スリープし、行を再度出力して再びスリープする 3 つの SwingWorker を作成する必要がありますSwingWorker

したがって、期待される出力は次のとおりです。

I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15)
I am thread with 1200 sleep in iteration 0: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 2: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 1: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 3: SwingWorker-pool-1-thread-1 (15)
I am thread with 1200 sleep in iteration 1: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 4: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 2: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 5: SwingWorker-pool-1-thread-1 (15)
I am thread with 500 sleep in iteration 6: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 3: SwingWorker-pool-1-thread-2 (16)
I am thread with 1200 sleep in iteration 2: SwingWorker-pool-1-thread-3 (17)
I am thread with 500 sleep in iteration 7: SwingWorker-pool-1-thread-1 (15)
.............

など、合計 150 行 (それぞれ 3 ワーカー x 50 回の反復)

代わりに、私が得る出力は次のとおりです。

I am thread with 500 sleep in iteration 0: SwingWorker-pool-1-thread-1 (15)
I am thread with 900 sleep in iteration 0: SwingWorker-pool-1-thread-2 (16)
I am thread with 500 sleep in iteration 1: SwingWorker-pool-1-thread-1 (15)

以上です。わずか3行。この後、プログラムは終了します。そのブロックのどこにもスタックトレースはありませんtry catch

1)。1200 ミリ秒のスリープのワーカーはどこにありますか? 実際、1200ms を 1000ms に置き換えると、このワーカーも 1 行を出力します... はい、1 行だけです。変...

2)。なぜ労働者は止まるのですか?(そして私は150行のものを手に入れません)

Windows 7 64 ビットで JRE 7 Update 11を使用してこのプログラムを実行しました。

PS:コンソールに表示されるスレッド ID として 2 つの異なる値 (15 と 16) を取得するため、ここで言及したバグはこのバージョンの JRE で修正されたと確信しています。これは私が最初に疑ったことでした。

4

4 に答える 4

9

SwingWorker クラスのソース コード (Java SE 7) の 771 行目を確認すると、次のようになります。

thread.setDaemon(true);

SwingWorkerがデーモン スレッド内で実行されることがわかります。Java では、すべての非デーモン スレッドが終了すると JVM が終了します。

于 2013-02-15T18:21:30.657 に答える
9

Swing イベント スレッドを維持するには、視覚化された Swing トップ レベル ウィンドウを表示する必要があると思います。そうしないと、デーモン以外のスレッドがないためにプログラムがシャットダウンします。

編集:
SwingWorker スレッドがデーモン スレッドであることを証明するには、コード行を追加してテストします。

System.out.println("I am thread with " + ms + " sleep in iteration "
   + i + ": " + t.getName() + " (" + t.getId() + ")");

// **** added
System.out.println("Daemon?: " + Thread.currentThread().isDaemon()); 
于 2013-02-15T18:10:55.243 に答える
4

すでに述べたように、UIを使用してスレッドを存続させることができます。

SwingWorker#getまたは、スレッドが終了するのを待つために(またはメインスレッドが終了するのを妨げるものを)使用することもできます。そうすることで、期待どおりの出力が得られます。これがあなたが望むことをする修正されたコードです。

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import java.util.concurrent.ExecutionException;

public class SwingWorkerTest
{
    public static void main (String[] args)
    {
        final MySwingWorker w1 = new MySwingWorker (500),
         w2 = new MySwingWorker (900),
         w3 = new MySwingWorker (1200);
        SwingUtilities.invokeLater (new Runnable ()
        {
            @Override
            public void run ()
            {
                w1.execute ();
                w2.execute ();
                w3.execute ();
            }
        });

        try{
            // you can replace the code in this block
            // by anything that keeps the program from 
            // terminating before the threads/SwingWorkers.
            w1.get();
            w2.get(); 
            w3.get(); 
        }catch(InterruptedException e){
            System.err.println("InterruptedException occured");
        }catch(ExecutionException e){
            System.err.println("InterruptedException occured");
        }

    }
}

class MySwingWorker extends SwingWorker<Void, Void>
{
    private int ms;

    public MySwingWorker (int ms)
    {
        this.ms = ms;
    }

    @Override
    protected Void doInBackground()
    {
        Thread t = Thread.currentThread ();

        for (int i = 0; i < 50; i++)
        {
            try
            {
                Thread.sleep (ms);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace ();
            }

            System.out.println ("I am thread with " + ms + " sleep in iteration " + i + ": " + t.getName () + " (" + t.getId () + ")");
        }

        return null;
    }
}
于 2013-02-15T18:27:21.347 に答える
3

UIを作成してみましたか?new Object().wait();または、メインスレッドが終了するのを防ぐために、メインの最後に何かを置きますか?

これが事実であるかどうかは完全にはわかりませんが、実際の UI が表示されていない場合、swing ワーカーは単なる別のスレッドであり、デーモン スレッドとして構成していないため、main がそれらを起動し、main であると確信しています。終了し、プロセスは終了しますか?

于 2013-02-15T18:11:34.967 に答える