2008-10-23 3 views
117

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

ответ

99

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

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

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

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

    • проверку Here более углубленной информации о том, как функционирует пул потоков под капотом

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

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

+5

Единственное, что я задаюсь вопросом о том, следующее заявление от MSDN (http://msdn.microsoft.com/en-us /library/1c9txz50.aspx) «Фоновый поток выполняется только тогда, когда количество выполняемых потоков переднего плана меньше числа процессоров». Значит ли это, что при разделении работы между ядрами приоритетные потоки становятся приоритетными? – cdiggins 2010-02-03 12:44:39

+1

➤ Вы не можете прервать или прервать поток из пула потоков. ➤ Вы не можете присоединиться к потоку из пула потоков. Чтобы достичь этого, вы должны использовать некоторые другие механизмы. – Zinov 2015-03-29 18:18:58

1

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

2

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

When should I not use the ThreadPool in .Net?

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

1

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

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

7

также

new Thread().Start()

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

+11

Вы всегда можете установить поток в фоновый режим. По умолчанию они просто переднего плана. – 2008-10-23 14:55:18

+0

Эрик, как это сделать? – 2009-05-11 15:44:18

0

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

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

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

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

13

В .NET удалось ThreadPool: -

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

Другие реализации пула потоков ex ist, что может быть более подходящим для длительных операций.

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

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

0

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

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

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

1

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

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

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

2

Я был любопытным относительно относительного использования ресурсов для них и провел тест на моем двухъядерном ноутбуке 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