views:

1043

answers:

7

For what I can read, it is used to dispatch a new thread in a swing app to perform some "background" work, but what's the benefit from using this rather than a "normal" thread?

Is not the same using a new Thread and when it finish invoke some GUI method using SwingUtilities.invokeLater?...

What am I missing here?

http://en.wikipedia.org/wiki/SwingWorker

http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html

+2  A: 

SwingWorker is an implementation of a common pattern (in .Net i read there is GuiWorker BackgroundWorker for this), where you have to do some work in a GUI program, but keep the GUI responsive. The problem is that often GUI libraries are not multi thread safe, so the common way to implement such workers is to use the message loop of the library to transfer messages into the event loop of the application.

These classes allow you to easily update your GUI. Usually, they have a update(int status) method that is called by the thread, dispatched by the class, and handled by the GUI, while the thread continues its work.

Using normal threads, you would need to code your own events or some other messaging mechanism for this task, which can be a pain if you need this functionality often. Using invokeLater in Java for example, you would intermix the code for updating the gui into the code for doing the work. The SwingWorker allows you to keep things separate.

Johannes Schaub - litb
You need listener with SwingWorker too. So?
OscarRyz
What i meant is that you would need own listeners (not listener interfaces already created) for your own event managing. SwingWorker handles all this for you. for example you can overwrite the method "done", which is called when the worker is finished.
Johannes Schaub - litb
Or you can easily just add a property change listener on the way
Johannes Schaub - litb
I see. So the code is clearer and maintainable because each time a new coder looks at the code he knows how the SwingWorker perform its job, rathern than having to "guess" what the new thread code is all about. ..
OscarRyz
Yes exactly that's my point
Johannes Schaub - litb
I'm coming from the C++ world. And i've coded a GuiWorker like that too. Before that, i had to send events back and forth between the GUI and the Threads. It was a pain in the ass. The GuiWorker made many things more easy. I could use it for the background search, filter and whatnot.
Johannes Schaub - litb
+1  A: 

to answer your question, you are not missing anything. this class is just a convenient utility for wrapping up the functionality you discribed (start another thread to do the background work and then invoking some final action on the EDT with the results).

+8  A: 

Yes, you can accomplish what a SwingWorker does with vanilla threads + invokeLater. SwingWorker provides a predictable, intergrated way to accomplish tasks on a background thread and report result on the EDT. SwingWorker additionally adds support for intermediate results. Again, you can do all of this yourself but sometimes it's easy to use the integrated and predictable solution especially when it comes to concurrency.

basszero
*cough* "integrated" way *cough*
Rob
+2  A: 

A code example:

import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx
                                             // another one is built in 
                                             // since JDK 1.6 AFAIK?

public class SwingWorkerTest {

  public static void main( String[] args ) {

    /**
      * First method
      */
    new Thread() {

      public void run() {

        /** Do work that would freeze GUI here */

        final Object result = new Object();
        java.awt.EventQueue.invokeLater( new Runnable() {

          public void run() {
          /** Update GUI here */
          }
        } );

      }
    }.start();

    /**
      * Second method
      */
    new SwingWorker< Object , Object >() {

      protected Object doInBackground() throws Exception {
        /** Do work that would freeze GUI here */

        return null;
      }

      protected void done() {
        try {
          Object result = get();
          /** Update GUI here */
        }
        catch ( Exception ex ) {
          ex.printStackTrace();
          if ( ex instanceof java.lang.InterruptedException )
            return;
        }
      }
    }.execute();
  }

}

The choice always depends on personal preference and use case.

The second method has an advantage when refactoring. You can more easily convert the anonymous class to an inner class when the method it's used in is too large.

My personal preference goes to the second, for we have built a framework where SwingWorkers can be added and are executed one after the other...

dhiller
A: 

SwingWorker makes trivial example code much more concise. However it creates a ball of mud. Communications to and from the GUI and executed logic are all welded together. So, I'd not like to see it used in real production code.

Tom Hawtin - tackline
A: 

SwingWorker is far easier than mucking with your own threads because it gives you two things that are painful to manually, thread coordination between the UI and the background process and doing loops effective, background work that keeps working and sending updates back to the UI incrementally, like process a large amount of data, or loading a large list. The disadvantage (or advantage) depends on how you look at it, is that it hides the underlying implementation, so future version may have different behavior, performance, etc, which may be undesirable. I've found it quite useful as the glue between a UI event and my own command code, the SwingWorker maintains the link to the UI and my code pumps data.

Paul Sagor
A: 

When working with Swing, it is important to know that the main swing processing (ie. rendering) happens on a single thread (which is not your main thread). This is often called the Swing or awt event thread. Those familiar with the JDK pre 1.6 will remember the "grey rectangle" bug if you spent too much time in an event dispatcher for a swing component. What does this mean. In any swing application you will have 2 threads running that you will now have to deal with. Normally if all your operations within an event dispatcher (the code that gets fired say when a button is clicked) is short (ie. changing the state of a siwng button) you can just run this inside of the event dispatcher. If your application is going to call a web service or a database, or you application state is driven by external events (ie. jms) or you want to just make your UI more interactive (ie. build a list of items and be able to do something else) you should use a thread other than the awt event thread (the main swing one). So in these cases you spawn a new thread and do what you have to, and when the results finally come back, you then somehow have to create an event that can be executed by the awt/swing dispatcher. SwingWorker is a great little design pattern that allows you do to do this (the other way is SwingUtilities). It is particularly useful for doing fetch data from external sources or say long calculations (rendering a graphics scene). It helps automate the dispatch and subsequent re-integration of the results from an external thread (other than the awt thread). For async events (ie. an event from JMS needs to update a result, use SwingUtilities).

nso1