Примеры, когда удобно использовать Executors.newSingleThreadExecutor()
Может кто-нибудь сказать мне пример из реальной жизни, где удобно использовать этот метод фабрики, а не другие?
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor ()
Создает Исполнителя, который использует один рабочий поток, работающий из неограниченной очереди. (Тем не менее, обратите внимание, что если этот единственный поток завершается из-за сбоя во время выполнения до завершения работы, то при необходимости для выполнения последующих задач его место занимает новый.) Задачи гарантированно выполняются последовательно, и не более одной задачи будет активной в любой момент времени. В отличие от эквивалентного newFixedThreadPool(1), возвращаемый исполнитель гарантированно не может быть реконфигурируем для использования дополнительных потоков.
Заранее спасибо.
4 ответа
Может кто-нибудь сказать мне пример из реальной жизни, где это удобно использовать [
newSingleThreadExecutor()
заводской метод], а не другие?
Я предполагаю, что вы спрашиваете, когда вы используете однопоточный пул потоков, а не фиксированный или кэшированный пул потоков.
Я использую однопоточный исполнитель, когда мне нужно выполнить много задач, но я хочу, чтобы это выполнял только один поток. Это то же самое, что и использование фиксированного пула потоков, равного 1, конечно. Часто это происходит потому, что нам не нужно, чтобы они выполнялись параллельно, это фоновые задачи, и мы не хотим использовать слишком много системных ресурсов (ЦП, память, ввод-вывод). Я хочу иметь дело с различными задачами, как Callable
или же Runnable
объекты так ExecutorService
является оптимальным, но все, что мне нужно, это один поток для их запуска.
Например, у меня есть ряд задач таймера, которые я добавляю весной. У меня есть два вида задач, и мои "краткосрочные" задачи выполняются в одном пуле потоков. Существует только один поток, который выполняет их все, хотя в моей системе их несколько сотен. Они выполняют рутинные задачи, такие как проверка дискового пространства, очистка журналов, вывод статистики и т. Д. Для задач, которые являются критичными по времени, я выполняю в пуле кэшированных потоков.
Другой пример - у нас есть ряд задач по интеграции партнеров. Они не занимают много времени и работают довольно редко, и мы не хотим, чтобы они конкурировали с другими системными потоками, поэтому они выполняются в однопоточном исполнителе.
Третий пример состоит в том, что у нас есть конечный автомат, где каждый из мутаторов состояний переводит работу из одного состояния в другое и регистрируется как Runnable
в одном пуле потоков. Несмотря на то, что у нас есть сотни мутаторов, только одна задача является допустимой в любой момент времени, поэтому нет смысла выделять более одного потока для этой задачи.
Помимо уже упомянутых причин, вы захотите использовать однопоточный исполнитель, когда вы хотите упорядочить гарантии, то есть вы должны убедиться, что любые задачи будут всегда выполняться в том порядке, в котором они были представлены.
Разница между Executors.newSingleThreadExecutor()
а также Executors.newFixedThreadPool(1)
небольшой, но может быть полезен при разработке API библиотеки. Если вы выставите возвращенный ExecutorService
пользователям вашей библиотеки, и библиотека работает корректно только тогда, когда исполнитель использует один поток (задачи не являются потокобезопасными), предпочтительно использовать Executors.newSingleThreadExecutor()
, В противном случае пользователь вашей библиотеки может сломать его, выполнив это:
ExecutorService e = myLibrary.getBackgroundTaskExecutor();
((ThreadPoolExecutor)e).setCorePoolSize(10);
, что невозможно для Executors.newSingleThreadExecutor()
,
Это полезно, когда вам нужен облегченный сервис, который только делает удобным откладывать выполнение задачи, и вы хотите убедиться, что для работы используется только один поток.