Download the JDK
Search the Tutorials
Hide the TOC
Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Section: Worker Threads and SwingWorker
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
Tasks that Have Interim Results

> It is often useful for a background task to provide interim results while it is still working. The task can do this by invoking `SwingWorker.publish`. This method accepts a variable number of arguments. Each argument must be of the type specified by `SwingWorker`'s second type parameter.

> To collect results provided by `publish`, override `SwingWorker.process` This method will be invoked from the event dispatch thread. Results from multiple invocations of `publish` are often accumulated for a single invocation of `process`.

> Let's look at the way the ``Flipper.java`` example uses `publish` to provide interim results. Click the Launch button to run `Flipper` using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

> This program tests the fairness of `java.util.Random` by generating a series of random `boolean` values in a background task. This is equivalent to flipping a coin; hence the name `Flipper`. To report its results, the background task uses an object of type `FlipPair`

> >     private static class FlipPair {
> >         private final long heads, total;
> >         FlipPair(long heads, long total) {
> >             this.heads = heads;
> >             this.total = total;
> >         }
> >     }

> The `heads` field is the number of times the random value has been `true`; the `total` field is the total number of random values.

> The background task is represented by an instance of `FlipTask`:

> >     private class FlipTask extends SwingWorker<Void, FlipPair> {

> Since the task does not return a final result, it does not matter what the first type parameter is; `Void` is used as a placeholder. The task invokes `publish` after each "coin flip":

> >     @Override
> >     protected Void doInBackground() {
> >         long heads = 0;
> >         long total = 0;
> >         Random random = new Random();
> >         while (!isCancelled()) {
> >             total++;
> >             if (random.nextBoolean()) {
> >                 heads++;
> >             }
> >             publish(new FlipPair(heads, total));
> >         }
> >         return null;
> >     }

> (The `isCancelled` method is discussed in the next section.) Because `publish` is invoked very frequently, a lot of `FlipPair` values will probably be accumulated before `process` is invoked in the event dispatch thread; `process` is only intested in the last value reported each time, using it to update the GUI:

> >     protected void process(List<FlipPair> pairs) {
> >         FlipPair pair = pairs.get(pairs.size() - 1);
> >         headsText.setText(String.format("%d", pair.heads));
> >         totalText.setText(String.format("%d", pair.total));
> >         devText.setText(String.format("%.10g",
> >                 ((double) pair.heads)/((double) pair.total) - 0.5));
> >     }

> If `Random` is fair, the value displayed in `devText` should get closer and closer to 0 as `Flipper` runs.

> > Note: The `setText` method used in `Flipper` is actually "thread safe" as defined in its specification. That means that we could dispense with `publish` and `process` and set the text fields directly from the worker thread. We've chosen to ignore this fact in order to provide a simple demonstration of `SwingWorker` interim results.

Previous page: Simple Background Tasks
Next page: Canceling Background Tasks