Подтвердить что ты не робот

Почему интерфейс ExecutorService не реализует AutoCloseable?

Сбой при вызове shutdown() для исполнителя потока приведет к тому, что приложение никогда не завершится.

Лучшая практика для закрытия ExecutorService заключается в следующем:

ExecutorService service = null;
try {
  service = Executors.newSingleThreadExecutor();
  // add tasks to thread executor
  …
} finally {
  if (service != null) service.shutdown();
}

Поскольку Java знает концепцию "попробуй с ресурсами", было бы неплохо, если бы мы могли это сделать?

try (service = Executors.newSingleThreadExecutor())
{
  // add tasks to thread executor
  …
} 
4b9b3361

Ответ 1

Что ExecutorService имеет фактически два действия, связанные с выключением; основанный на простом факте, что оба способы закрытия службы имеют смысл.

Таким образом: как бы вы автоматически закрыли сервис? В последовательном порядке, который работает для всех?!

Итак, разумное объяснение в моих глазах: вы не можете сделать ExecutorService автоматической блокировкой, потому что у этой службы нет единой операции закрытия; но два!

И если вы считаете, что можете использовать такое автоматическое закрытие, запись вашей собственной реализации с использованием "делегирования" будет за 5 минут! Или, вероятно, 10 минут, потому что вы создадите одну версию, вызывающую shutdown() как закрытую операцию; и тот, который делает shutdownNow() вместо этого.

Ответ 2

Это посредственный обходной путь

ExecutorService service = Executors.newSingleThreadExecutor();
try (Closeable close = service::shutdown) {

}

Или, если проверенное исключение беспокоит вас, вы можете написать:

interface MyCloseable extends AutoCloseable {
    void close();
}

А потом

ExecutorService service = Executors.newSingleThreadExecutor();
try (MyCloseable close = service::shutdown) {

}

Конечно, вы никогда не должны помещать что-либо между присваиванием и оператором try и не использовать локальную переменную service после оператора try.

Учитывая предостережения, просто используйте, finally вместо этого.

Ответ 3

Я не вижу, что AutoCloseable является полезным для Исполнителя. try-with-resources - это вещи, которые могут быть инициализированы, использованы и выпущены в рамках метода. Это отлично подходит для таких вещей, как файлы, сетевые подключения, ресурсы jdbc и т.д., Где они быстро открываются, используются и быстро очищаются. Но исполнитель, особенно threadpool, - это то, что вы хотите использовать в течение длительного периода времени, возможно, в течение всего срока службы приложения и, как правило, впрыскивается в такие вещи, как singleton-сервисы, которые могут иметь метод, который инфраструктура DI знает вызовите выключение приложения, чтобы очистить исполнитель. Эта схема использования отлично работает без использования ресурсов try-with.

Кроме того, большой мотиватор, стоящий за попытками использования ресурсов, заключается в том, что исключения не маскируются. Это не так много для исполнителей, все бросание исключений будет происходить в задачах, переданных исполнителю, маскирование исключений не является проблемой.

Ответ 4

Try-with-resources - это автоматическое закрытие Readers/Streams, где ExecutorService - это выполнение задач с использованием пула потоков.

Таким образом, я не уверен, существует ли параллель между двумя, что мы можем думать о применении try-with-resources к ExecutorServices.

ОБНОВЛЕНО
Цитирование спецификации языка Java:

Оператор try-with-resources параметризуется переменными (называемыми ресурсами), которые инициализируются перед исполнением блока try и автоматически закрываются в обратном порядке, из которого они были инициализированы, после выполнения блока try. catch и предложение finally часто не нужны, когда ресурсы автоматически закрываются.

Спектр вызывает переменные как "ресурсы". Поэтому я не уверен, что ExecutorService можно назвать ресурсом, и поэтому не думайте, что ExecutorService как параллель с Readers/Streams/Statement/ResultSet/Connection и т.д.