В чем именно разница между размером основного пула и максимальным размером пула, когда мы говорим о них ThreadPoolExecutor
?
Можно ли это объяснить на примере?
java
asynchronous
threadpoolexecutor
пользователь2568266
источник
источник
Ответы:
Из этого сообщения в блоге :
источник
allowCoreThreadTimeOut(boolean)
который позволяет убивать основные потоки после заданного времени простоя. Установка этого значения в true и установкаcore threads
=max threads
позволяет пулу потоков масштабироваться от 0 доmax threads
.ЕСЛИ запущенные потоки> corePoolSize & <maxPoolSize , то создайте новый поток , если общая очередь задач заполнена и прибывает новый.
Форма документа: (Если количество запущенных потоков превышает corePoolSize, но меньше maximumPoolSize , новый поток будет создан только в том случае, если очередь заполнена.)
Теперь возьмем простой пример,
Здесь 5 - это corePoolSize - означает, что Jvm создаст новый поток для новой задачи для первых 5 задач. и другие задачи будут добавляться в очередь, пока она не заполнится (50 задач).
10 - это maxPoolSize - JVM может создавать максимум 10 потоков. Означает, что если уже запущено 5 задач / потоков и очередь заполнена 50 ожидающими задачами, и если в очередь поступает еще один новый запрос / задача, тогда JVM создаст новый поток до 10 (общее количество потоков = предыдущие 5 + новые 5) ;
new ArrayBlockingQueue (50) = - это общий размер очереди - в ней можно поставить в очередь 50 задач.
после того, как все 10 потоков будут запущены, и если появится новая задача, эта новая задача будет отклонена.
Правила создания потоков внутри SUN:
Если количество потоков меньше, чем corePoolSize, создайте новый поток для запуска новой задачи.
Если количество потоков равно (или больше) corePoolSize, поместите задачу в очередь.
Если очередь заполнена, а количество потоков меньше maxPoolSize, создайте новый поток для выполнения задач.
Если очередь заполнена, а количество потоков больше или равно maxPoolSize, отклоните задачу.
Надеюсь, это HelpFul .. и, пожалуйста, поправьте меня, если я ошибаюсь ...
источник
Из документа :
Более того:
источник
Если вы решите создать класс
ThreadPoolExecutor
вручную вместо использованияExecutors
фабричного класса, вам нужно будет создать и настроить его с помощью одного из его конструкторов. Самый обширный конструктор этого класса:Как видите, вы можете настроить:
Ограничение количества задач в очереди
Ограничение количества одновременно выполняемых задач, определение размера вашего пула потоков представляет собой огромное преимущество для вашего приложения и его среды выполнения с точки зрения предсказуемости и стабильности: создание неограниченного потока в конечном итоге приведет к исчерпанию ресурсов времени выполнения, и ваше приложение может столкнуться с этим. , серьезные проблемы с производительностью, которые могут привести даже к нестабильности приложения.
Это решение только одной части проблемы: вы ограничиваете количество выполняемых задач, но не ограничиваете количество заданий, которые могут быть отправлены и поставлены в очередь для последующего выполнения. Позже приложение столкнется с нехваткой ресурсов, но в конечном итоге оно испытает ее, если скорость отправки будет постоянно превышать скорость выполнения.
Решение этой проблемы: Предоставление очереди блокировки исполнителю для хранения ожидающих задач. В случае заполнения очереди отправленное задание будет «отклонено».
RejectedExecutionHandler
Вызывается , когда представление задачи отвергается, и именно поэтому глагол отвергается был цитируемых в предыдущем пункте. Вы можете реализовать свою собственную политику отказа или использовать одну из встроенных политик, предоставляемых платформой.В политиках отклонения по умолчанию исполнитель создает файл
RejectedExecutionException
. Однако другие встроенные политики позволяют:источник
Источник
Правила для размера
ThreadPoolExecutor's
пула обычно неправильно понимаются, потому что он работает не так, как вы думаете, или так, как вы этого хотите.Возьмите этот пример. Размер начального пула потоков - 1, размер основного пула - 5, максимальный размер пула - 10, а очередь - 100.
Способ Sun: по мере поступления запросов в потоках будет создано до 5, затем задачи будут добавляться в очередь до тех пор, пока она не достигнет 100. Когда очередь заполнится, новые потоки будут созданы до
maxPoolSize
. Как только все потоки будут использованы и очередь заполнена, задачи будут отклонены. По мере уменьшения очереди уменьшается и количество активных потоков.Ожидаемый пользователем способ: по мере поступления запросов в потоках будет создано до 10, затем задачи будут добавлены в очередь, пока не достигнет 100, после чего они будут отклонены. Количество потоков будет переименовано в максимальное, пока очередь не станет пустой. Когда очередь пуста, потоки отмирают, пока не
corePoolSize
останутся.Разница в том, что пользователи хотят начать увеличивать размер пула раньше и хотят, чтобы очередь была меньше, тогда как метод Sun хочет сохранить размер пула небольшим и увеличивать его только тогда, когда нагрузка становится слишком большой.
Вот простые правила Sun для создания потоков:
corePoolSize
, создайте новый поток для запуска новой задачи.corePoolSize
, поместите задачу в очередь.maxPoolSize
, создайте новый поток для выполнения задач.maxPoolSize
, отклоните задачу. Суть в том, что новые потоки создаются только при заполнении очереди, поэтому, если вы используете неограниченную очередь, количество потоков не будет превышатьcorePoolSize
.Более полное объяснение можно получить из уст лошадей:
ThreadPoolExecutor
документация по API.Есть действительно хорошее сообщение на форуме, в котором рассказывается, как
ThreadPoolExecutor
работает эта работа с примерами кода: http://forums.sun.com/thread.jspa?threadID=5401400&tstart=0Подробнее: http://forums.sun.com/thread.jspa?threadID=5224557&tstart=450
источник
Вы можете найти определение терминов corepoolsize и maxpoolsize в javadoc. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
По ссылке выше есть ответ на ваш вопрос. Однако просто чтобы было понятно. Приложение будет продолжать создавать потоки, пока не достигнет corePoolSize. Я думаю, что идея здесь в том, что этого количества потоков должно хватить для обработки потока задач. Если новая задача приходит после создания потоков corePoolSize, задачи будут поставлены в очередь. Как только очередь будет заполнена, исполнитель начнет создавать новые потоки. Это своего рода балансировка. По сути, это означает, что поток задач превышает вычислительную мощность. Итак, Executor снова начнет создавать новые потоки, пока не достигнет максимального количества потоков. Опять же, новые потоки будут созданы тогда и только тогда, когда очередь заполнена.
источник
Хорошее объяснение в этом блоге:
Иллюстрация
Вывод :
источник
Из книги Основы согласования Java :
CorePoolSize : ThreadPoolExecutor имеет атрибут corePoolSize, который определяет, сколько потоков он будет запускать до тех пор, пока новые потоки не будут запущены только при заполнении очереди
MaximumPoolSize : этот атрибут определяет максимальное количество запущенных потоков. Вы можете установить это значение в Integer. MAX_VALUE, чтобы не было верхней границы
источник
java.util.concurrent.ThreadPoolExecutor
источник
Понимание внутреннего поведения
ThreadPoolExecutor
при отправке новой задачи помогло мне понять, чемcorePoolSize
и чемmaximumPoolSize
отличаются.Позволять:
N
быть количество потоков в пуле,getPoolSize()
. Активные потоки + свободные потоки.T
быть количеством задач, переданных исполнителю / пулу.C
быть основной размер пула,getCorePoolSize()
. Сколько потоков может быть создано не более чем в пуле для входящих задач, прежде чем новые задачи попадут в очередь .M
быть максимальный размер пула,getMaximumPoolSize()
. Максимальное количество потоков, которое может выделить пул.Поведение
ThreadPoolExecutor
в Java при отправке новой задачи:N <= C
незанятым потокам не назначается новая входящая задача, вместо этого создается новый поток.N > C
и если есть незанятые потоки, то там назначается новая задача.N > C
а если нет НИКАКИХ праздные темы, новые задачи ставятся в очередь. НЕТ НОВОЙ НИТИ ЗДЕСЬ НЕ СОЗДАНО.M
. ЕслиM
достигается, мы отклоняем задачи. Здесь важно не создавать новые потоки, пока очередь не заполнится!Источники:
Примеры
Пример с
corePoolSize = 0
иmaximumPoolSize = 10
с емкостью очереди50
.В результате в пуле будет один активный поток, пока в очереди не будет 50 элементов.
Пример с
corePoolSize = 10
иmaximumPoolSize = 10
с емкостью очереди50
.В результате в пуле будет 10 активных потоков. Когда в очереди будет 50 элементов, задачи будут отклонены.
источник