Почему ScheduledThreadPoolExecutor принимает только фиксированное количество потоков? - PullRequest
30 голосов
/ 28 июля 2010

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

Но, похоже,что я могу указать только фиксированное количество потоков для пула, почему так?

Ответы [ 3 ]

11 голосов
/ 28 июля 2010

Как почему, я тоже не знаю.Но я могу себе представить.

Количество ресурсов компьютера ограничено.Не все ресурсы могут обрабатываться одновременно.

Если несколько процессов одновременно загружают файлы, они будут загружаться медленнее, чем если бы они загружались последовательно (по крайней мере, на жесткий диск).

Процессортакже имеет ограниченную поддержку одновременной обработки нескольких потоков.В какой-то момент ОС или JVM будут тратить больше времени на переключение потоков, чем потоки тратят на выполнение своего кода.

Это хорошая причина для того, чтобы ScheduledThreadPoolExecutor был спроектирован таким, какой он есть.Вы можете поместить любое количество заданий в очередь, но никогда не выполняется больше заданий одновременно, чем может быть эффективно выполнено.Конечно, это зависит от вас.

Если ваши задачи связаны с вводом-выводом, я бы установил небольшой размер пула, а если он связан с процессором, немного больше (32 или около того).Вы также можете сделать несколько ScheduledThreadPoolExecutor с, один для задач, связанных с вводом-выводом, и один для задач, связанных с процессором.

7 голосов
/ 29 августа 2010

Продолжая копаться о SchecduledThreadPoolExecutor, я обнаружил, что ссылка , эта ссылка объясняет, что SchecduledThreadPoolExecutor решает многие проблемы класса Timer.А также поводом для введения SchecduledThreadPoolExecutor была замена Timer (из-за различных проблем с Timer).Я думаю, что причина для фиксированного числа потоков, передаваемых SchecduledThreadPoolExecutor, в одной из проблем, решаемых этим классом.т.е.

Класс Timer запускает только один поток.Хотя это более эффективно, чем создание потока для каждой задачи, оно не является оптимальным решением.Оптимальным решением может быть использование нескольких потоков между одним потоком для всех задач и одним потоком на задачу.По сути, лучшим решением является размещение задач в пуле потоков.Количество потоков в пуле должно быть назначаемым во время построения, чтобы позволить программе определить оптимальное количество потоков в пуле.

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

Надеюсь, это поможет:)

4 голосов
/ 29 августа 2010

В соответствии с Java-параллелизмом на практике существуют следующие недостатки создания неограниченного потока:

Затраты на жизненный цикл потока

Создание потока и разборкане бесплатны.Создание потока требует времени и требует некоторой обработки со стороны JVM и ОС.

Потребление ресурсов

Активные потоки потребляют системные ресурсы, особенно память.Если потоков больше, чем доступных процессоров, потоки работают без дела.Наличие большого количества незанятых потоков может связать много памяти, оказать давление на сборщик мусора, а наличие множества потоков, конкурирующих за ЦП, также может привести к снижению производительности.Если у вас достаточно потоков, чтобы все процессоры были заняты, создание дополнительных потоков не поможет, а может даже повредит.

Стабильность

Существует ограничение на количествотемы могут быть созданы.Ограничение зависит от платформы и зависит от таких факторов, как параметры вызова JVM, запрошенный размер стека в конструкторе Thread и ограничения на потоки, размещенные базовой операционной системой.Когда вы достигнете предела htis, наиболее вероятным результатом будет OutOfMemoryError.Попытка восстановиться после такой ошибки очень рискованна;гораздо проще структурировать вашу программу, чтобы избежать превышения этого предела.


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

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

...