问题
I wanted to try out some ideas using SwingWorker
since I haven't used it too much. Instead, I ran into an issue and I can't figure out what's wrong.
Here's a short SSCCE that demonstrates this problem (I know people here like SSCCEs):
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;
}
}
So my program should create 3 SwingWorkers that print a line on the screen then sleep for the specified number of milliseconds and then print the line again and sleep again etc. I create the SwingWorker
s from within Swing's thread because otherwise they wouldn't even start.
So the expected output is:
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)
.............
and so on for a total of 150 lines (3 workers x 50 iterations for each)
Instead, the output I get is:
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)
And that's it. Just 3 lines. After this the program exits. There's no stacktrace anywhere from that try catch
block.
1). Where is the worker with the 1200ms sleep ? Actually, if I replace 1200ms with 1000ms, then this worker also prints 1 line... yes, only one. Weird...
2). Why do the workers stop ? (and I don't get 150 lines of stuff)
I ran this program using JRE 7 Update 11 on Windows 7 64-bit.
PS: I'm pretty sure that the bug mentioned here was fixed in this version of JRE, since I do get 2 distinct values (15 and 16) as thread ID's printed on the console. This was the first thing I suspected.
回答1:
I believe that you need to show a visualized Swing top level Window in order to keep the Swing event thread alive. Otherwise the program will shut down for lack of non-daemon threads.
Edit:
To prove that the SwingWorker thread is a Daemon thread, just add a line of code to test it:
System.out.println("I am thread with " + ms + " sleep in iteration "
+ i + ": " + t.getName() + " (" + t.getId() + ")");
// **** added
System.out.println("Daemon?: " + Thread.currentThread().isDaemon());
回答2:
If you look at line 771 of SwingWorker class source code (Java SE 7):
thread.setDaemon(true);
You will see that the SwingWorker
is executed within a daemon thread, and in Java the JVM will be terminated if all non-daemon threads are finished.
回答3:
As already mentioned, you can use the UI to keep the threads alive.
Alternatively, what you can do is use SwingWorker#get
(or anything that prevents the main thread from terminating) to wait for the threads to finish. By doing so, you will get the output as expected. Here is the modified code, that does what you want.
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;
}
}
回答4:
Have you tried creating any UI? or putting something like new Object().wait();
at the end of main, to prevent the main thread from exiting?
I'm not entirely sure that this is the case, but without any actual UI showing, i'm pretty sure the swing workers are just another thread, and you haven't configured any as daemon threads, so main starts them up, main finishes, and the process exits?
来源:https://stackoverflow.com/questions/14900697/why-does-swingworker-stop-unexpectedly