Как Keep-alive работает с ThreadPoolExecutor?

Продолжая вопроса, отправленного мной , Я пытаюсь использовать ThreadPoolExecutor в моей кодовой базе. Даже после неоднократных попыток понять из документа Java API я не смог четко понять функциональность / цель параметра keepAliveTime, который должен быть передан в конструктор. Надеюсь, кто-нибудь сможет объяснить мне хороший рабочий пример.

Выдержки из документа Java:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)

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


person Gnanam    schedule 30.04.2012    source источник
comment
С точки зрения терминологии, вы дважды использовали слово «реализовать», когда я думаю, вы просто имели в виду использование. Вы не пытаетесь реализовать ThreadPoolExecutor, написав свой собственный код, реализующий этот API - вы просто создаете ThreadPoolExecutor и хотите знать, как он будет себя вести, верно?   -  person Jon Skeet    schedule 30.04.2012
comment
Да, ты прав. Я просто имел в виду, что это новый вид реализации в моей кодовой базе.   -  person Gnanam    schedule 30.04.2012
comment
Но это не реализация of ThreadPoolExecutor. Это действительно полезно, если вы можете правильно использовать терминологию - особенно в Stack Overflow.   -  person Jon Skeet    schedule 30.04.2012
comment
Да конечно. Спасибо, что поправили меня.   -  person Gnanam    schedule 30.04.2012


Ответы (3)


Предположим, у вас есть размер ядра 5 и максимальный размер 15. По какой-то причине ваш пул становится занятым и использует все 15 доступных потоков. В конце концов у вас заканчивается работа, поэтому некоторые из ваших потоков становятся простаивающими, когда завершают свою последнюю задачу. Итак, 10 из этих потоков могут умереть.

Однако, чтобы избежать их слишком быстрого уничтожения, вы можете указать время сохранения активности. Таким образом, если вы указали 1 в качестве значения keepAliveTime и TimeUnit.MINUTE в качестве значения unit, каждый поток будет ждать одну минуту после завершения выполнения задачи, чтобы увидеть, есть ли еще работа, которую нужно выполнить. Если бы ему все еще не было дано больше работы, он позволил бы себе завершиться до тех пор, пока в пуле не останется только 5 потоков - «ядро» пула.

person Jon Skeet    schedule 30.04.2012
comment
Если я правильно понял, keepAliveTime используется / эффективно только тогда, когда потоки в пуле имеют размер больше ядра. Это не применимо, когда потоки в пуле меньше размера ядра. - person Gnanam; 30.04.2012
comment
Извините, если этот вопрос слишком простой. Но почему мы хотим поддерживать потоки, которые действительно завершили выполнение задачи? Во всяком случае, максимальное количество потоков (maximumPoolSize), разрешенное в пуле, ограничено, верно? - person Gnanam; 30.04.2012
comment
Смысл уничтожения потоков такой же, как и с точки зрения наличия пула потоков в первую очередь - не тратить лишние ресурсы. - person Marko Topolnik; 30.04.2012
comment
@Gnanam - чтобы потоки могли выполнять другую задачу, экономя накладные расходы на создание нового потока. - person Martin James; 30.04.2012
comment
@MartinJames и @Marko: Спасибо за разъяснения. Это означает, что по поводу моего другого вопроса - параметр keepAliveTime имеет смысл только тогда, когда потоки в пуле имеют размер больше ядра - правильно ли я понимаю? - person Gnanam; 30.04.2012
comment
@Gnanam: Я тоже так понимаю. Это не значит, что это обязательно правильно, но, по крайней мере, это будет согласованно :) - person Jon Skeet; 30.04.2012
comment
@JonSkeet. Что на самом деле означает, что поток простаивает. Допустим, я создал 10 потоков. Задача, представленная потоку, содержит только один сетевой вызов, будет ли поток, ожидающий сетевого вызова, считаться бездействующим. - person Prabhath; 28.03.2016
comment
@Prabhath: Предполагая, что ожидание сетевого вызова означает, что он выполняет сетевой вызов и блокирует его до завершения, тогда нет, он не простаивает - это блок. Если бы он простаивал, ему можно было бы дать другое задание. Если он заблокирован, этого не может быть. - person Jon Skeet; 28.03.2016
comment
@JonSkeet Спасибо, вот о чем я спрашивал - person Prabhath; 29.03.2016
comment
@user_x: Есть что-то, что заставляет вас думать, что это не так? - person Jon Skeet; 18.05.2016
comment
@Gnanam Это также может быть применено к основным потокам. Из документов: By default, the keep-alive policy applies only when there are more than corePoolSize threads. But method {@link #allowCoreThreadTimeOut(boolean)} can be used to apply this time-out policy to core threads as well, so long as the keepAliveTime value is non-zero. - person Zaheer; 07.11.2016
comment
Меня также интересовало, как потоки в пуле сохраняются / удаляются, если keepAliveTime равно 0. Ответ: здесь: значение времени, равное нулю, приведет к немедленному завершению избыточных потоков после выполнения задач. И 0 используется в newFixedThreadPool - person Maksim Dmitriev; 07.01.2017

Вот еще описание из Javadoc:

<dt>Keep-alive times</dt>
 *
 * <dd>If the pool currently has more than corePoolSize threads,
 * excess threads will be terminated if they have been idle for more
 * than the keepAliveTime (see {@link
 * ThreadPoolExecutor#getKeepAliveTime}). This provides a means of
 * reducing resource consumption when the pool is not being actively
 * used. If the pool becomes more active later, new threads will be
 * constructed. This parameter can also be changed dynamically
 * using method {@link ThreadPoolExecutor#setKeepAliveTime}. Using
 * a value of <tt>Long.MAX_VALUE</tt> {@link TimeUnit#NANOSECONDS}
 * effectively disables idle threads from ever terminating prior
 * to shut down.
 * </dd>
 *

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

person Francis Upton IV    schedule 30.04.2012

Вот пример кода, демонстрирующего работу keepAliveTime Как работает maximumPoolSize ThreadPoolExecutor?

person Dmitry Krivenko    schedule 27.07.2016