sun.com/docs/books/tutorial/uiswing/misc/threads.html"> How to Use Threads for more details):
- Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive.
- Swing components should be accessed on the Event Dispatch Thread only.
These constraints mean that a GUI application with time intensive computing needs at least two threads: 1) a thread to perform the lengthy task and 2) the
Event Dispatch Thread (EDT) for all GUI-related activities. This involves inter-thread communication which can be tricky to implement.
{@code SwingWorker} is designed for situations where you need to have a long running task run in a background threadand provide updates to the UI either when done, or while processing. Subclasses of {@code SwingWorker} must implementthe {@link #doInBackground} method to perform the background computation.
Workflow There are three threads involved in the life cycle of a {@code SwingWorker} :
- Current thread: The {@link #execute} method is called on this thread. It schedules {@code SwingWorker} for theexecution on a worker thread and returns immediately. One can wait for the {@code SwingWorker} to completeusing the {@link #get get} methods.
- Worker thread: The {@link #doInBackground} method is called on this thread. This is where all backgroundactivities should happen. To notify {@code PropertyChangeListeners} about bound properties changes use the {@link #firePropertyChange firePropertyChange} and {@link #getPropertyChangeSupport} methods. By default there are two boundproperties available: {@code state} and {@code progress}.
- Event Dispatch Thread: All Swing related activities occur on this thread. {@code SwingWorker} invokes the{@link #process process} and {@link #done} methods and notifies any {@code PropertyChangeListeners} on this thread.
Often, the
Current thread is the
Event Dispatch Thread.
Before the {@code doInBackground} method is invoked on a
worker thread, {@code SwingWorker} notifies any{@code PropertyChangeListeners} about the {@code state} property change to {@code StateValue.STARTED}. After the {@code doInBackground} method is finished the {@code done} method is executed. Then {@code SwingWorker} notifies any{@code PropertyChangeListeners} about the {@code state} property change to {@code StateValue.DONE}.
{@code SwingWorker} is only designed to be executed once. Executing a {@code SwingWorker} more than once will notresult in invoking the {@code doInBackground} method twice.
Sample Usage The following example illustrates the simplest use case. Some processing is done in the background and when done you update a Swing component.
Say we want to find the "Meaning of Life" and display the result in a {@code JLabel}.
final JLabel label; class MeaningOfLifeFinder extends SwingWorker<String, Object> { {@code @Override}public String doInBackground() { return findTheMeaningOfLife(); } {@code @Override}protected void done() { try { label.setText(get()); } catch (Exception ignore) { } } } (new MeaningOfLifeFinder()).execute();
The next example is useful in situations where you wish to process data as it is ready on the
Event Dispatch Thread.
Now we want to find the first N prime numbers and display the results in a {@code JTextArea}. While this is computing, we want to update our progress in a {@code JProgressBar}. Finally, we also want to print the prime numbers to {@code System.out}.
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> { PrimeNumbersTask(JTextArea textArea, int numbersToFind) { //initialize } {@code @Override}public List<Integer> doInBackground() { while (! enough && ! isCancelled()) { number = nextPrimeNumber(); publish(number); setProgress(100 * numbers.size() / numbersToFind); } } return numbers; } {@code @Override}protected void process(Integer... chunks) { for (int number : chunks) { textArea.append(number + "\n"); } } } JTextArea textArea = new JTextArea(); final JProgressBar progressBar = new JProgressBar(0, 100); PrimeNumbersTask task = new PrimeNumbersTask(textArea, N); task.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } } }); task.execute(); System.out.println(task.get()); //prints all prime numbers we have got
Because {@code SwingWorker} implements {@code Runnable}, a {@code SwingWorker} can be submitted to an {@link java.util.concurrent.Executor} for execution.
@param < T> the result type returned by this {@code SwingWorker's} {@code doInBackground} and {@code get} methods
@param < V> the type used for carrying out intermediate results by this {@code SwingWorker's} {@code publish} and{@code process} methods
Note: This is a backport from java 1.6