如何从Callable返回临时结果?

时间:2012-01-20 20:54:01

标签: java multithreading publish executorservice

我使用Callable执行了ExecutorService个对象。

如何从此可调用项返回中间结果?

我知道Swing有javax.swing.SwingWorker#publish(results)但我不使用Swing。

5 个答案:

答案 0 :(得分:2)

有几种方法可以做到这一点。你可以用回调来做,或者你可以用队列来做。

以下是使用回调执行此操作的示例:

public static interface Callback<T> {
    public void on(T event);
}

然后,回调的实现与您正在进行的事件有关:

final Callback<String> callback = new Callback<String>() {
    public void on(String event) {
        System.out.println(event);
    }
};

现在您可以在池中使用回调:

Future<String> submit = pool.submit(new Callable<String>() {
    public String call() throws Exception {
        for(int i = 0; i < 10; i++) {
            callback.on("process " + i);
        }
        return "done";
    }
});

答案 1 :(得分:1)

目前尚不清楚“临时结果”究竟是什么。并发包中使用的接口根本不定义它,但假设方法类似于或多或少的纯函数。

因此,改为:

interim     = compute something
finalresult = compute something else

做这样的事情:

interim = compute something
final1 = new Pair( interim, fork(new Future() { compute something else }) )

(Pseudocode,想传达这个想法,不是可编译的代码)


编辑这个想法是:不是运行单个单片计算块(碰巧达到一些“临时结果”可用的状态)而是将其分解,以便第一个任务返回前“临时”结果,并且同时,分叉计算最终结果的第二个任务。当然,必须将此任务的句柄传递给调用者,以便最终获得最终结果。通常,这是通过Future接口完成的。

答案 2 :(得分:1)

您可以将AtomicInteger传递给您的类(执行程序将提交的那个),在该类中增加它的值,并从调用线程中检查它&# 39; s值

这样的事情:

public class LongComputation {

private AtomicInteger progress = new AtomicInteger(0);

public static void main(String[] args) throws InterruptedException,
        ExecutionException {

    AtomicInteger progress = new AtomicInteger(0);
    LongComputation computation = new LongComputation(progress);

    ExecutorService executor = Executors.newFixedThreadPool(2);
    Future<Integer> result = executor.submit(() -> computation.compute());
    executor.shutdown();

    while (!result.isDone()) {
        System.out.printf("Progress...%d%%%n", progress.intValue());
        TimeUnit.MILLISECONDS.sleep(100);
    }

    System.out.printf("Result=%d%n", result.get());
}

public LongComputation(AtomicInteger progress) {
    this.progress = progress;
}

public int compute() throws InterruptedException {

    for (int i = 0; i < 100; i++) {
        TimeUnit.MILLISECONDS.sleep(100);
        progress.incrementAndGet();
    }

    return 1_000_000;
}

}

答案 3 :(得分:0)

您要找的是java.util.concurrent.Future

  

Future表示异步计算的结果。方法   用于检查计算是否完成,等待它   完成,并检索计算结果。结果   只能在计算时使用方法get检索   完成,必要时阻止,直到准备就绪。取消是   由取消方法执行。提供了其他方法   确定任务是否正常完成或已取消。一旦   计算完成后,计算无法取消。如果你   我希望使用Future来取消可取性,但不是   提供可用的结果,您可以声明Future表单的类型   并且由于底层任务而返回null。

答案 4 :(得分:0)

如果要将推送中间结果发布,则必须使用Observer / Observerable之类的内容来推广自己的API。更简单的方法是通过一些自定义方法轮询当前状态。