Как вернуть промежуточные результаты из Callable? - PullRequest
4 голосов
/ 21 января 2012

У меня есть Callable объект, выполненный с использованием ExecutorService.

Как вернуть промежуточные результаты этого вызова?

Я знаю, что есть javax.swing.SwingWorker#publish(results) для Swing, но я не использую Swing.

Ответы [ 5 ]

2 голосов
/ 21 января 2012

Есть несколько способов сделать это.Вы можете сделать это с помощью обратного вызова или вы можете сделать это с помощью очереди.

Вот пример выполнения этого с обратным вызовом:

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 голос
/ 22 марта 2015

Вы можете передать, скажем, AtomicInteger вашему классу (тот, который будет отправлен исполнителем), внутри этого класса вы увеличиваете его значение, а из вызывающего потока вы проверяете его значение

Примерно так:

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;
}

}

1 голос
/ 21 января 2012

Не ясно, что на самом деле является «промежуточным результатом».Интерфейсы, используемые в пакете параллелизма, просто не определяют это, а предполагают методы, которые напоминают более или менее чистые функции.

Следовательно, вместо этого:

interim     = compute something
finalresult = compute something else

делает что-то вроде этого:

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

(Псевдокод, мысль, которая передает идею, а не компилируемый код)


РЕДАКТИРОВАТЬ Идея такова: вместо запуска одного монолитного блока вычислений (который достигаетсостояние, в котором доступны некоторые «промежуточные результаты») разбить его так, чтобы первая задача возвращала прежний «промежуточный» результат, и в то же время размечать вторую задачу, которая вычисляет конечный результат.Конечно, дескриптор этой задачи должен быть доставлен вызывающей стороне, чтобы в конечном итоге он мог получить конечный результат.Обычно это делается с помощью интерфейса Future.

0 голосов
/ 21 января 2012

Вы должны будете свернуть свой собственный API с чем-то вроде Observer / Observerable, если вы хотите опубликовать промежуточные результаты в виде push. Проще было бы просто опросить текущее состояние с помощью некоторого самостоятельно определенного метода.

0 голосов
/ 21 января 2012

То, что вы ищете, это java.util.concurrent.Future .

Будущее представляет собой результат асинхронных вычислений. методы предоставляются, чтобы проверить, если вычисление завершено, ждать его завершение, и получить результат вычисления. Результат может быть получен только с использованием метода get, когда вычисление завершено, блокировка при необходимости, пока он не будет готов. Отмена выполняется методом отмены. Дополнительные методы предоставляются определить, было ли задание выполнено нормально или было отменено. Когда вычисление завершено, вычисление не может быть отменено. если ты хотел бы использовать будущее ради отменяемости, но не предоставить полезный результат, вы можете объявить типы формы Future и вернуть ноль в результате основной задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...