barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

четверг, 19 июля 2012 г.

ScheduledThreadPoolExecutor и setMaximumPoolSize

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 и проверкой реального размера пула я ждал промежуток времени, достаточный, чтобы все задачи по разу отработали):



Комментариев нет:

Отправить комментарий