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
example uses Flipper.java
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; } }
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> {
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; }
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 interested 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)); }
Random
is fair, the value displayed in
devText
should get closer and closer to 0 as
Flipper
runs.
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.