java.util.concurrent.ScheduledThreadPoolExecutor использует фиксированный пул потоков, определяемый свойством corePoooSize. Вызов scheduler.setMaximumPoolSize() ни к чему не приводит, и если число задач больше чем corePoolSize, они стоят в очереди в ожидании свободного потока, даже если время их выполнения подошло.
НО никто не мешает вызовом setCorePoolSize() в любой момент жизни ScheduledThreadPoolExecutor`а увеличить или уменьшить этот размер пула. Увеличение размера приводит к моментальному созданию нового потока (если очередь scheduler.getQueue() непуста, т.е. не все задачи разобраны свободными потоками), а вот с уменьшением не всё так просто.
Дело в том, что класс ThreadPoolExecutor.Worker устроен таким образом, что даже если число потоков в пуле превышает установленный corePoolSize, освободившийся поток все равно попытается взять из очереди задач очередную задачу, и завершится только если задачи там нет и ждать её ему пришлось больше, чем промежуток времени, устанавливаемый вызовом setKeepAliveTime():
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
Специфика периодических задач ScheduledThreadPoolExecutor`а такова, что если число задач больше corePoolSize, в очереди всегда есть задачи, поэтому Worker всегда получит задачу вызовом workQueue.poll и завершаться не станет, даже если размер пула превышает заданный corePoolSize().
Таким образом, динамическое уменьшение corePoolSize возымеет эффект только когда число потоков в пуле станет меньше числа запланированных задач.
Ниже приведен небольшой график, полученный экспериментально (между изменениями размера corePoolSize и проверкой реального размера пула я ждал промежуток времени, достаточный, чтобы все задачи по разу отработали):
Комментариев нет:
Отправить комментарий