Why does SwingWorker stop unexpectedly?

I wanted to try some ideas using SwingWorker , since I did not use it too much. Instead, I had a problem and I canโ€™t understand what happened.

Here's a short SSCCE that demonstrates this problem (I know people here as 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; } } 

So, my program should create 3 SwingWorkers that print a line on the screen, then sleep in the specified number of milliseconds, and then print the line again and sleep again, etc. I create a SwingWorker from a Swing thread, because otherwise they wonโ€™t even start.

Thus, the expected result:

 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) ............. 

etc. for a total of 150 lines (3 work 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) 

What is it. Only 3 lines. After that, the program will exit. There is no stacktrace from this try catch .

one). Where is the worker with a sleep of 1200 ms? Actually, if I replace 1200 ms with 1000 ms, then this worker also prints 1 line ... yes, only one. Weird ...

2). Why do workers stop? (and I don't get 150 rows)

I ran this program using JRE 7 Update 11 on Windows 7 64-bit .

PS: I am sure that the error mentioned here has been fixed in this version of the JRE, since I get 2 different values โ€‹โ€‹(15 and 16) as a stream identifier printed on the console. That was the first thing I suspected.

+8
java multithreading concurrency swing swingworker
source share
4 answers

I believe you need to show the Swing top-level rendered window to keep the Swing event stream alive. Otherwise, the program will be disabled due to the lack of threads without a daemon.

Edit:
To prove that the SwingWorker stream is a Daemon stream, simply 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()); 
+9
source share

If you look at line 771 of the source code for the SwingWorker class (Java SE 7):

 thread.setDaemon(true); 

You will see that SwingWorker is running in the daemon thread, and in the Java JVM will terminate if all non-daemon threads are terminated.

+9
source share

As already mentioned, you can use the user interface to save streams.

Alternatively, you can use SwingWorker#get (or anything that prevents the main thread from completing) to wait for the threads to finish. By doing so, you will get the result as expected. Here is a 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
source share

Have you tried to create any user interface? or put something like new Object().wait(); to the end of main to prevent the main thread from exiting?

Iโ€™m not quite sure that this is so, but without any actual display of the user interface, Iโ€™m sure that the work-swing is just one more thread, and you havenโ€™t configured any of them as daemon threads, so their main beginning is up. basic finishes and the process comes out?

+3
source share

All Articles