# 具有中期业绩的任务

> 原文： [https://docs.oracle.com/javase/tutorial/uiswing/concurrency/interim.html](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/interim.html)

在后台任务仍在工作时提供中间结果通常很有用。任务可以通过调用 [`SwingWorker.publish`](https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html#publish-V...-) 来完成。此方法接受可变数量的参数。每个参数必须是`SwingWorker`的第二个类型参数指定的类型。

要收集`publish`提供的结果，覆盖 [`SwingWorker.process`](https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html#process-java.util.List-) 将从事件派发线程调用此方法。 `publish`的多次调用的结果通常在`process`的单次调用中累积。

让我们看一下 [``Flipper.java``](../examples/concurrency/FlipperProject/src/concurrency/Flipper.java)示例使用`publish`提供中间结果的方式。单击启动按钮以使用 [Java™Web Start](http://www.oracle.com/technetwork/java/javase/javawebstart/index.html) （[下载 JDK 7 或更高版本](http://www.oracle.com/technetwork/java/javase/downloads/index.html)）运行`Flipper`。或者，要自己编译并运行示例，请参考[示例索引](../examples/concurrency/index.html#Flipper)。

[![Launches the Flipper example](img/4707a69a17729d71c56b2bdbbb4cc61c.jpg)](https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/FlipperProject/Flipper.jnlp)

该程序通过在后台任务中生成一系列随机`boolean`值来测试 [`java.util.Random`](https://docs.oracle.com/javase/8/docs/api/java/util/Random.html) 的公平性。这相当于掷硬币;因此名称`Flipper`。要报告其结果，后台任务使用`FlipPair`类型的对象

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

```

`heads`字段是随机值`true`的次数; `total`字段是随机值的总数。

后台任务由`FlipTask`的实例表示：

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

```

由于任务没有返回最终结果，因此第一个类型参数是什么并不重要; `Void`用作占位符。任务在每次“硬币翻转”后调用`publish`：

```
@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`方法将在下一节中讨论。）因为非常频繁地调用`publish`，所以在事件调度线程中调用`process`之前可能会累积很多`FlipPair`值。 `process`仅对每次报告的最后一个值感兴趣，使用它来更新 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`是公平的，`Flipper`运行时，`devText`中显示的值应越来越接近 0。

* * *

**Note:** The `setText` method used in `Flipper` is actually "thread safe" as defined in its [specification](https://docs.oracle.com/javase/8/docs/api/javax/swing/text/JTextComponent.html#setText-java.lang.String-). 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.

* * *