Какой механизм межпотокового взаимодействия может одновременно ожидать и освобождать базовый ресурс потока? - PullRequest
1 голос
/ 02 августа 2020

Я ищу механизм межпотокового взаимодействия, который может одновременно ожидать и освобождать базовый ресурс потока. В моем примере ниже, когда executorService инициализируется только 1 потоком, вторая задача будет зависать, потому что поток удерживается t1, даже если это await. Приведенный ниже код будет работать, только если вы измените инициализацию executorService двумя потоками.

public static void main(String[] args) {
  ExecutorService executorService = Executors.newFixedThreadPool(1);
  CountDownLatch cdl = new CountDownLatch(1);

  executorService.submit(() -> {
    System.out.println("start t1");
    try {
      cdl.await();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("t1 done");
  });

  executorService.submit(() -> {
    System.out.println("start t2");
    cdl.countDown();
    System.out.println("t2 done");
  });

  System.out.println("Master thread ends");
}

Вывод, когда executorService инициализируется 1 потоком.

start t1
Master thread ends

вывод, когда executorService инициализируется двумя потоками.

start t1
Master thread ends
start t2
t2 done
t1 done

В идеале, когда t1 ожидает, ему не нужно удерживать базовый поток, чтобы задача 2 могла выполняться в этом пуле потоков. Реальный вариант использования этой проблемы заключается в том, что если у меня есть пул потоков, и задачи будут отправлены / запланированы обратно в тот же пул для повторных попыток. Теоретически процесс зависнет, когда все отправленные задачи немедленно завершатся неудачно, потому что нет потоков для выполнения задач повтора.

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

1 Ответ

0 голосов
/ 02 августа 2020

Единственный способ освободить базовый ресурс потока - это полностью вернуться из основного метода задачи (обычно Runnable :: run). Для одновременного ожидания производитель событий должен быть подписан асинхронным способом. Не у всех производителей есть асинхронный интерфейс. CompletbleFuture имеет (метод whenComplete), а CountDownLatch - нет. Однако вы можете расширить CountDownLatch с помощью асинхронной функциональности, подписаться на его завершение, вернуться из run () и ждать. Я сделал это в своей DF4J библиотеке: AsyncCountDownLatch. java

...