Исполнители Java: как получить уведомление, не блокируя, когда задача завершена? - PullRequest
128 голосов
/ 05 мая 2009

Скажем, у меня есть очередь, полная задач, которые мне нужно отправить в службу исполнителя. Я хочу, чтобы они обрабатывались по одному. Самый простой способ, который я могу придумать, это:

  1. Возьмите задание из очереди
  2. Отправить его исполнителю
  3. Вызовите .get для возвращенного Future и заблокируйте, пока не будет доступен результат
  4. Возьми еще одно задание из очереди ...

Однако я стараюсь полностью не блокировать. Если у меня будет 10 000 таких очередей, для которых нужно обрабатывать свои задачи по одной, я исчерпаю пространство стека, потому что большинство из них будут удерживать заблокированные потоки.

То, что я хотел бы, это отправить задачу и предоставить обратный вызов, который вызывается, когда задача завершена. Я буду использовать это уведомление об обратном вызове в качестве флага для отправки следующего задания. (функционал java и jetlang, очевидно, используют такие неблокирующие алгоритмы, но я не могу понять их код)

Как я могу это сделать, используя java.util.concurrent JDK, если не считать написания моей собственной службы исполнителя?

(очередь, которая питает меня этими задачами, может сама блокироваться, но это проблема, которую необходимо решить позже)

Ответы [ 11 ]

0 голосов
/ 09 января 2016

Вы можете использовать реализацию Callable так, чтобы

public class MyAsyncCallable<V> implements Callable<V> {

    CallbackInterface ci;

    public MyAsyncCallable(CallbackInterface ci) {
        this.ci = ci;
    }

    public V call() throws Exception {

        System.out.println("Call of MyCallable invoked");
        System.out.println("Result = " + this.ci.doSomething(10, 20));
        return (V) "Good job";
    }
}

, где CallbackInterface является чем-то очень простым, как

public interface CallbackInterface {
    public int doSomething(int a, int b);
}

и теперь основной класс будет выглядеть так

ExecutorService ex = Executors.newFixedThreadPool(2);

MyAsyncCallable<String> mac = new MyAsyncCallable<String>((a, b) -> a + b);
ex.submit(mac);
...