Bookmark Topic Watch Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Report post to moderator
A common problem posted in the Swing forum is something of this nature: "I created a JProgressBar and update its value, but the display doesn't change". An example of some code exhibiting this behavior is as follows:



I suggest that you copy the above code, compile and run it so you can get a sense of the problem.

If you have run the code, you will witness that the console reports each value of i set in actionPerformed but the GUI is not updated until the for loop is complete. Those with sharp eyes will also notice that the button "Do Something" remains depressed until the loop is complete. This is broken, for sure, but what is the problem?

The code that paints the GUI and events generated by the GUI are executed on a single thread, called the "event-dispatching thread". (If you've never heard of "threads", consult the Java Tutorial on Threads here: http://java.sun.com/docs/books/tutorial/essential/threads/index.html. Threads make it possible to do several things at the same time in a single program.) In the program above, we are using the event-dispatching thread to run the for loop. While we are using it, the event-dispatching thread is unable to update the GUI. Hence the JProgressBar remaining at position 0 and the JButton appearing to be depressed until the for loop completes.

Now that we've identified the problem, how do we fix it? The answer in your case will depend on your program requirements and your comfort level with threads. The Java Swing Tutorial has a page on Using Threads with Swing (http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html) which is a good starting point for fixing this problem.

The simplest solution would be to create a new thread to handle the long-running for loop, freeing the event dispatch thread to do its work. If the use of wait/notify to synchronized the threads in the code below confuses you, see the Java Tutorial on Threads (http://java.sun.com/docs/books/tutorial/essential/threads/index.html) for an explanation.


Now when one presses the button "Do Something", the event dispatch thread notifies the thread in our class and continues on its way. The worker thread does the heavy lifting in the for loop and the event dispatch thread is free to keep the GUI up to date. The JProgressBar updates smoothly and the JButton remains depressed only as long as we hold the mouse down.

One may ask why we just didn't create the thread when it is needed (i.e. in the actionPerformed() method). The most obvious reason is that threads aren't cheap. Each thread requires that stack memory and native resources be allocated. Those resources need to be freed when the thread has run its course. This is unnecessary churn when one can create one long-lived thread and dispatch work to it as needed.

A more subtle reason is that a child thread inherits the parent thread's priority. Priority determines which thread gets run when. Higher priority threads get more CPU time than lower. Threads of equal priority may share CPU time or run to the exclusion of the other equal priority threads, depending on the JVM implementation. If we create a thread to handle our work in the actionPerformed method, the parent thread is the event dispatch thread. The two threads would have the same priority and the worker thread could monopolize the CPU, starving the event dispatch thread. The end result would be the same behavior we saw in the test1 code: the GUI not being updated.


CategoryCodeSamples
 
Don't get me started about those stupid light bulbs.
    Bookmark Topic Watch Topic
  • New Topic