• Post Reply Bookmark Topic Watch Topic
  • New Topic

Java 1.6.0.20 broke my SwingWorker threads!  RSS feed

 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was previously running Sun Java 1.6.0.16 and have been designing a Swing GUI for use on my team at work. Everything was working great and my teammate and I were going to release the initial version to our team for testing next week. However, today I updated from 1.6.0.16 to 1.6.0.20 and now my worker threads don't seem to properly update the JProgressBar object that I have defined. The progress bar is set to visible but never gets updated until work is done and then it just bumps it up to 100%, sleeps 500ms, and returns.

What I am doing is essentially:

1. Listening for a particular action to occur.
2. When the action occurs I kick off a method inside of a worker thread (let's call it ThreadA).
3. That method also spawns it's own child thread (ThreadB) to smoothly update the progress bar while it works (in my actual program I estimate the time required to process based on a linear regression I performed previously and pass that estimate as an argument to ThreadB. For the example below I just hard-code 5000ms).
4. When work in ThreadA is done, a boolean is set to false and processing stops -- meaning that the status bar should be at 100% and then disappear.
5. Then ThreadB dies (followed shortly thereafter by ThreadA).


I have come up with a fairly simple example below (it was about the smallest I could do and still make it mimic my code) to demonstrate the behavior that I am describing. Can anyone tell me why this worked in 1.6.0.16 but fails in 1.6.0.20? Am I not following some particular coding guidelines with SwingWorker or is this just a bug that was introduced in the latest JRE?


 
Rob Spoor
Sheriff
Posts: 21050
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
doInBackground, and therefore also updateStatusBar, runs in the SwingWorker's own thread. Updates to the GUI should be done from the Event Dispatcher Thread (EDT). You may want to change the SwingWorker's type to SwingWorker<String,Integer>, then use publish / process to do the real updates to the progress bar:
Edit: I just re-read your code, and are you actually calling a SwingWorker from a SwingWorker? I really suggest you refresh your knowledge about concurrency in Swing.
 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Edit: I just re-read your code, and are you actually calling a SwingWorker from a SwingWorker? I really suggest you refresh your knowledge about concurrency in Swing.

Absolutely. I went back and read Sun's tutorial here:

http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

I don't see anywhere in there that spawning child threads of threads is considered sacrilege (processes fork child processes all the time). Yes, I realize there is a difference between threads and processes but still -- I never read anything that told me not to do it, and it works flawlessly until 1.6.0.20. Other than perhaps some scheduling issues (obviously the embedded thread cannot get scheduled if the parent thread isn't currently scheduled for execution), can you offer any information why this is such a crime?

I guess I will attempt two different strategies. My options are:

1. Move the embedded thread out so that the EDT spawns the background process and then spawns a second worker to update the status bar (both will be direct children of the EDT).
2. Use publish/process instead of (or in conjunction with) option #1.


Let's see if I can get by using option #1 only.
 
Rob Spoor
Sheriff
Posts: 21050
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
B Mayes wrote:I don't see anywhere in there that spawning child threads of threads is considered sacrilege (processes fork child processes all the time). Yes, I realize there is a difference between threads and processes but still -- I never read anything that told me not to do it, and it works flawlessly until 1.6.0.20. Other than perhaps some scheduling issues (obviously the embedded thread cannot get scheduled if the parent thread isn't currently scheduled for execution), can you offer any information why this is such a crime?

It's not a crime, but it's highly unusual to do something in the background of doing something in the background.

Let's see if I can get by using option #1 only.

Make sure that all changes to the user interface must occur on the EDT. Not just increasing the value, also changing the text of the progress bar.
 
pete stein
Bartender
Posts: 1561
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe that there have been some changes to the internals of SwingWorker making calling another SwingWorker from within a SwingWorker behave differently, and this has been reported to the bug database.

Please check out:
bug_id=6880336
bug_id=6480289
and:
Sun Forum, threadID=5424356

Good luck and HTH
 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow thank you Pete. I have spent a few hours today trying to debug and/or rewrite my code to no avail. This explains a lot! Looks like I'm going to have to revert back to 1.6.0.17 or earlier. Thanks a lot Sun...


Rob, thanks for your help too. I tried changing things to use process/publish but clearly due to the above bug, that didn't fix the behavior either. But I appreciate your efforts.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!