Какой вариант использования для неограниченной очереди в Java Executors? - PullRequest
0 голосов
/ 24 декабря 2018

Executors фабрика из Java использует неограниченную очередь отложенных задач.Например, Executors.newFixedThreadPool использует new LinkedBlockingQueue, который не ограничен для принятия задач.

public static ExecutorService newFixedThreadPool(int nThreads) {
  return new ThreadPoolExecutor(nThreads, nThreads,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>());
}

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

Каков сценарий использования этого подхода на самом деле?Почему создатели Java не использовали ограниченную очередь?Я не могу представить сценарий, когда неограниченное лучше ограниченного, но я могу что-то упустить.Может кто-нибудь дать достойное объяснение?Лучший!

Ответы [ 4 ]

0 голосов
/ 24 декабря 2018

Поскольку вы спрашиваете об «сценарии использования», все очень просто: каждый раз, когда у вас есть много отдельных задач, которые вы в конечном итоге хотите завершить.Скажите, что вы хотите скачать сотни тысяч файлов?Создайте задачу загрузки для каждого, отправьте ExecutorService, дождитесь завершения.Задачи в конце концов закончатся, так как вы больше не добавляете, и нет предела для ограничения.

0 голосов
/ 24 декабря 2018

Это подход по умолчанию, и пользователь может выбрать переход в ограниченную очередь.

Теперь, может быть, ваш вопрос: почему это значение по умолчанию?

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

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

0 голосов
/ 24 декабря 2018

Задачи могут добавляться в очередь на неопределенное время, вызывая OutOfMemoryError

Нет.Очередь на самом деле не unbouned, для неограниченного LinkedBlockingQueue она capacity равна Integer.MAX_VALUE(2147483647).Когда места недостаточно, RejectedExecutionHandler будет обрабатывать новые задачи прибытия.И обработчик по умолчанию - AbortPolicy, он будет прерывать новые задачи напрямую.

Я не могу представить сценарий, когда неограниченный лучше ограниченного

Пользователи могут не заботиться о размере очереди или просто не хотят ограничивать кэшированные задачи.

Если вы заботитесь об этом, вы можете создать ThreadPoolExecutor с пользовательскимconstrutor.

0 голосов
/ 24 декабря 2018

Вы можете отклонить задачи, используя ArrayBlockingQueue (ограниченная очередь блокировки)

final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100);
executorService = new ThreadPoolExecutor(n, n,
    0L, TimeUnit.MILLISECONDS,
    queue);

Код выше эквивалентен Executors.newFixedThreadPool (n)однако вместо LinkedBlockingQueue по умолчанию мы используем ArrayBlockingQueue с фиксированной емкостью 100. Это означает, что если 100 задач уже поставлены в очередь (и n выполняется), новая задача будет отклонена с RejectedExecutionException.

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