Тема против ThreadPool - PullRequest
       35

Тема против ThreadPool

130 голосов
/ 23 октября 2008

В чем разница между использованием нового потока и использованием потока из пула потоков? Какие преимущества в производительности и почему я должен рассмотреть использование потока из пула, а не одного, который я явно создал? Я имею в виду конкретно .NET здесь, но общие примеры хороши.

Ответы [ 10 ]

105 голосов
/ 23 октября 2008

Пул потоков обеспечит преимущества для частых и относительно коротких операций

  • Повторное использование уже созданных потоков вместо создания новых (дорогостоящий процесс)
  • Регулирование скорости создания потоков при наличии большого количества запросов на новые рабочие элементы (я полагаю, это только в .NET 3.5)

    • Если вы ставите в очередь 100 задач пула потоков, он будет использовать только столько потоков, сколько уже было создано для обслуживания этих запросов (например, 10). Пул потоков будет делать частые проверки (я думаю, каждые 500 мс в 3.5 SP1), и если есть задачи в очереди, он создаст один новый поток. Если ваши задачи выполняются быстро, то количество новых потоков будет небольшим, и повторное использование 10 или более потоков для коротких задач будет быстрее, чем создание 100 потоков заранее.

    • Если в вашей рабочей нагрузке постоянно поступает большое количество запросов на пул потоков, то пул потоков настроится на вашу рабочую нагрузку, создавая больше потоков в пуле с помощью описанного выше процесса, чтобы было больше потоков доступны для обработки запросов

    • проверьте Здесь для более подробной информации о том, как функционирует пул потоков под колпаком

Создание нового потока самостоятельно было бы более уместным, если бы задание было относительно продолжительным (вероятно, около секунды или двух, но это зависит от конкретной ситуации)

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

14 голосов
/ 23 октября 2008

Управляемый поток .NET: -

  • Размеры зависят от текущей рабочей нагрузки и доступного оборудования
  • Содержит рабочие потоки и потоки порта завершения (которые специально используются для обслуживания ввода-вывода)
  • Оптимизирован для большого количества относительно коротких операций

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

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

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

8 голосов
/ 23 октября 2008

также

new Thread().Start()

порождает поток переднего плана, который не умрет, если вы закроете свою программу. Потоки ThreadPool - это фоновые потоки, которые умирают при закрытии приложения.

7 голосов
/ 01 февраля 2016

Меня интересовало относительное использование ресурсов для них, и я провел тест на моем двухъядерном ноутбуке Intel i5 2012 года, используя сборку выпуска .net 4.0 на Windows 8. Пул потоков занимал в среднем 0,035 мс, чтобы начать там, где потоки в среднем 5,06 мс. Другими словами, поток в пуле запускается примерно в 300 раз быстрее для большого количества недолговечных потоков. По крайней мере, в тестируемом диапазоне (100-2000) потоков общее время на поток казалось довольно постоянным.

Это код, который был протестирован:

    for (int i = 0; i < ThreadCount; i++) {
        Task.Run(() => { });
    }

    for (int i = 0; i < ThreadCount; i++) {
        var t = new Thread(() => { });
        t.Start();
    }

enter image description here

3 голосов
/ 23 октября 2008

Проверьте здесь для более ранней темы:

Когда я не должен использовать ThreadPool в .Net?

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

1 голос
/ 22 февраля 2015

Основная потребность в потоках theadpool состоит в том, чтобы обрабатывать небольшие небольшие задачи, которые, как ожидается, завершатся почти мгновенно. Аппаратные обработчики прерываний часто выполняются в контексте стека, который не подходит для неядерного кода, но аппаратный обработчик прерываний может обнаружить, что обратный вызов завершения пользовательского режима должен быть запущен как можно скорее. Создание нового потока для запуска такой вещи было бы огромным излишним. Наличие нескольких предварительно созданных потоков, которые можно отправить для выполнения обратных вызовов завершения ввода-вывода или других подобных вещей, намного эффективнее.

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

Если нельзя ожидать, что метод завершится в течение 100 мс или около того, когда он начнет выполнение, метод должен выполняться другими способами, помимо пула основного потока. Если нужно выполнить много задач, которые интенсивно загружают ЦП, но не будут блокировать, может быть полезно распределить их с помощью пула потоков приложений (по одному на ядро ​​ЦП), который отделен от «основного» пула потоков, поскольку использование большее количество потоков, чем ядер, будет контрпродуктивным при выполнении неблокирующих ресурсоемких задач. Однако если выполнение метода займет секунду или дольше и большую часть времени он будет заблокирован, метод, скорее всего, должен выполняться в выделенном потоке и почти наверняка не должен выполняться в потоке основного потока. Если длительная операция должна быть вызвана чем-то вроде обратного вызова ввода / вывода, нужно либо запустить поток для длительной операции до обратного вызова и заставить его ждать на мониторе, который пульсирует обратный вызов, либо пусть обратный вызов запускает новый поток для выполнения операции во время выхода обратного вызова, эффективно возвращая свой собственный поток в пул потоков.

1 голос
/ 23 октября 2008

Если вам нужно много потоков, вы, вероятно, хотите использовать ThreadPool. Они повторно используют потоки, избавляя вас от накладных расходов на создание потоков.

Если вам нужен только один поток, чтобы что-то сделать, поток, вероятно, самый простой.

1 голос
/ 23 октября 2008

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

0 голосов
/ 08 января 2014

Использование пула - хорошая идея, если вы не знаете или не можете контролировать, сколько потоков будет создано.

Просто возникла проблема с формой, использующей поток, чтобы обновить какое-то поле из базы данных для события с измененным положением элемента управления списком (избегайте замораживания). Моему пользователю потребовалось 5 минут, чтобы получить ошибку из базы данных (слишком много связи с Access), потому что он слишком быстро менял позицию списка ...

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

0 голосов
/ 23 октября 2008

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

Могут быть и системные причины. В Java (опять же, я не знаю, относится ли это к .NET), диспетчер потоков может применять специфичные для потока переменные, когда каждый поток извлекается из пула, и сбрасывать их при возврате (обычный способ передать что-то вроде личность).

Пример ограничения: У меня только 10 дБ соединений, поэтому я бы разрешил только 10 рабочих потоков для доступа к базе данных.

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

...