SwingWorker
From Wikipedia, the free encyclopedia
SwingWorker is a popular utility class developed by Sun Microsystems for the Swing library of the Java programming language. SwingWorker
enables proper use of the event dispatching thread. As of Java 6, SwingWorker
is included in the JRE.
Several incompatible, unofficial, versions of SwingWorker were produced from 1998 to 2006, and care must be taken to avoid the abundant documentation on these versions predating Java 6.
Contents |
[edit] Usage in Java 6.0
[edit] The event dispatching thread problem
SwingWorker is useful when a time-consuming task has to be performed following a user-interaction event (for example, parsing a huge XML File, on pressing a Button). The most straightforward way to do it is :
private Document doc; ... JButton button = new JButton("Open XML"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doc = loadXML(); } });
This will work, but unfortunately, the loadXML()
method will be called in the same thread as the main Swing thread, so if the method needs time to perform, the GUI will freeze during this time.
[edit] SwingWorker solution
This problem is not specific to Java, but common to many GUI models. SwingWorker
propose a way to solve it by performing the time-consuming task on another background thread, keeping the GUI responsive during this time.
[edit] Creating the worker
The following code defines the SwingWorker, which encapsulate the loadXML()
method call :
SwingWorker worker = new SwingWorker<Document, Void>() { public Document doInBackground() { Document intDoc = loadXML(); return intDoc; } };
[edit] Worker execution
The execution is called by using the SwingWorker.execute()
method.
[edit] Retrieving the result
The result can be retrieved by using the SwingWorker.get()
method.
As calling get()
on the Event Dispatch Thread blocks all events, including repaints, from being processed until the task completes, one must avoid to perform it before the lengthy operation has finished. There are two ways to retrieve the result after the task completion :
- override the
SwingWorker.done()
method. This method is called on the main EDT thread.
private Document doc; ... SwingWorker worker = new SwingWorker<Document, Void>() { public Document doInBackground() { Document intDoc = loadXML(); return intDoc; } public void done() { doc = get(); } };
- register a listener by using the worker
SwingWorker.addPropertyChangeListener(PropertyChangeListener)
method. The listener will be notified of changes in the worker state.
[edit] Complete Worker example
private Document doc; ... JButton button = new JButton("Open XML"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SwingWorker worker = new SwingWorker<Document, Void>() { public Document doInBackground() { Document intDoc = loadXML(); return intDoc; } public void done() { doc = get(); } }; worker.execute(); } });
[edit] See also
- Swing (Java)
- Event dispatching thread
- BackgroundWorker, the equivalent .NET Framework class
[edit] External links
- Worker Threads and SwingWorker from Sun's Java 6 Concurrency in Swing tutorial.
- Improve Application Performance With SwingWorker in Java SE 6 by John O'Conner, January 2007.
[edit] Outdated tutorials
- Customize SwingWorker to improve Swing GUIs article on JavaWorld [Note: this refers to an earlier, somewhat incompatible, non-library version of SwingWorker from 2003. Needs to be replaced with better reference.]
- Tutorial on SwingWorker Thread usage from SwingWiki.org [Note: Outdated as above.]