В чем разница между использованием нового потока и использованием потока из пула потоков? Какие преимущества в производительности есть и почему я должен рассматривать использование потока из пула, а не я, который я создал? Я здесь конкретно рассматриваю .NET, но общие примеры в порядке.
Тема против ThreadPool
Ответ 1
Пул потоков предоставит преимущества для частых и относительно коротких операций с помощью
- Повторное использование потоков, которые уже созданы вместо создания новых (дорогостоящий процесс)
-
Уменьшение скорости создания потоков при наличии пакета запросов для новых рабочих элементов (я считаю, что это только в .NET 3.5)
-
Если вы ставите в очередь 100 задач пула потоков, он будет использовать столько потоков, сколько уже было создано для обслуживания этих запросов (например, 10). Пул потоков проведет частые проверки (я считаю, каждые 500 мс в 3.5 SP1), и если есть задачи с постами, он будет создавать один новый поток. Если ваши задачи быстрые, количество новых потоков будет небольшим и повторное использование 10 или около того потоков для коротких задач будет быстрее, чем создание 100 потоков вверх.
-
Если в вашей рабочей нагрузке постоянно поступает большое количество запросов пула потоков, тогда пул потоков настроится на вашу рабочую нагрузку, создав больше потоков в пуле описанным выше процессом, чтобы было большее количество потоков доступный для обработки запросов
-
check Здесь для более подробной информации о том, как пул потоков работает под капотом
-
Создание нового потока было бы более подходящим, если бы работа была относительно продолжительной (вероятно, примерно через секунду или два, но это зависит от конкретной ситуации)
@Krzysztof - потоки потоков нитей - это фоновые потоки, которые останавливаются при завершении основного потока. Созданные вручную потоки по умолчанию являются приоритетными (будут продолжать работать после окончания основного потока), но могут быть установлены в фоновом режиме, прежде чем вызывать "Начать".
Ответ 2
Управляемый потоком .NET: -
- Размеры, основанные на текущей рабочей нагрузке и доступном оборудовании
- Содержит потоки рабочих потоков и потоки портов завершения (которые специально используются для обслуживания IO)
- Оптимизирован для большого количества относительно коротких операций
Существуют другие реализации пула потоков, которые могут быть более подходящими для длительных операций.
В частности, используйте пул потоков, чтобы ваше приложение не создавало слишком много потоков. Самая важная особенность потока - рабочая очередь. То есть, как только ваш компьютер будет достаточно занят, threadpool будет ставить в очередь запросы, а не сразу порождать больше потоков.
Итак, если вы создадите небольшое ограниченное количество потоков, создайте их самостоятельно. Если вы не можете определить, сколько потоков может быть создано (например, они созданы в ответ на входящий IO), и их работа будет недолговечной, используйте threadpool. Если вы не знаете, сколько, но их работа будет длительной, на платформе вам нечего помочь, но вы можете найти альтернативные реализации threadpool, которые подходят.
Ответ 3
также
new Thread().Start()
spawns Forefront thread, который не умрет, если вы закроете свою программу. ThreadPool потоки являются фоновыми потоками, которые умирают при закрытии приложения.
Ответ 4
Посмотрите на более ранний поток:
Когда мне не следует использовать ThreadPool в .Net?
Резюме состоит в том, что Threadpool хорош, если вам нужно создать много короткоживущих потоков, тогда как использование Threads дает вам немного больше контроля.
Ответ 5
Я был любопытным относительно относительного использования ресурсов для них, и провел тест на моем двухъядерном ноутбуке Intel i5 2012 года, используя версию выпуска .net 4.0 на Windows 8. Пулы потоков в среднем заняли 0,035 мс, чтобы начать, когда Threads взяли в среднем 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();
}
Ответ 6
Потоковое локальное хранилище не является хорошей идеей с пулами потоков. Это дает потокам "идентичность"; не все потоки равны. Теперь пулы потоков особенно полезны, если вам просто нужна куча одинаковых потоков, готовая выполнять свою работу без накладных расходов на создание.
Ответ 7
Если вам нужно много потоков, вы, вероятно, захотите использовать ThreadPool. Они повторно используют потоки, сохраняя при этом накладные расходы на создание потоков.
Если вам нужен только один поток, чтобы сделать что-то, Thread, вероятно, самый простой.
Ответ 8
Первичная потребность в потоках theadpool заключается в том, чтобы обрабатывать короткие небольшие задачи, которые, как ожидается, будут завершены почти мгновенно. Обработчики аппаратных прерываний часто выполняются в контексте стекирования, который не подходит для не-ядрового кода, но обработчик аппаратного прерывания может обнаружить, что обратный вызов завершения ввода-вывода должен быть запущен как можно скорее. Создание нового потока с целью запуска такой вещи было бы массовым излишеством. Наличие нескольких предварительно созданных потоков, которые могут быть отправлены для выполнения обратных вызовов завершения ввода-вывода или других подобных вещей, намного эффективнее.
Ключевым аспектом таких потоков является то, что если методы завершения ввода-вывода всегда выполняются практически мгновенно и никогда не блокируются, а число таких потоков, которые в настоящее время запускают такие методы, по меньшей мере равно числу процессоров, единственный способ любой другой поток может работать до того, как один из вышеперечисленных способов завершится, если один из других методов блокирует или его время выполнения превышает обычный срез времени потока; ни одно из них не должно происходить очень часто, если пул потоков используется по назначению.
Если ожидать, что метод не сможет выйти в течение 100 мс или около того, когда он начнет выполнение, метод должен быть выполнен с помощью некоторых средств, отличных от пула основных потоков. Если у вас есть много задач для выполнения, которые интенсивно работают с ЦП, но не будут блокироваться, может быть полезно отправить их с использованием пула потоков приложений (по одному на ядро центрального процессора), который отделен от "основного" потока, поскольку использование больше потоков, чем ядер, будет контрпродуктивным при выполнении неблокирующих задач с интенсивным использованием ЦП. Если, однако, какой-то метод займет второй или более длительный период и будет блокировать большую часть времени, этот метод, скорее всего, будет выполняться в выделенном потоке и почти наверняка не будет выполняться в потоке main-threadpool. Если долговременная работа должна быть вызвана чем-то вроде обратного вызова ввода-вывода, нужно либо начать поток для долговременной операции перед обратным вызовом, либо ждать на мониторе, который импульс обратного вызова, или иначе иметь обратный вызов запускать новый поток для выполнения операции, в то время как обратный вызов завершается, эффективно возвращая свой собственный поток в threadpool.
Ответ 9
В общем случае (я никогда не использовал .NET) пул потоков использовался для управления ресурсами. Он позволяет настраивать ограничения в вашем программном обеспечении. Это также может быть сделано по соображениям производительности, поскольку создание новых потоков может быть дорогостоящим.
Также могут быть и системные причины. В Java (опять же я не знаю, относится ли это к .NET), менеджер потоков может применять зависящие от потока переменные, поскольку каждый поток вытягивается из пула и отменяет их при их возврате (обычный способ передать что-то вроде тождество).
Пример ограничения: У меня только 10 db-соединений, поэтому я бы разрешил только 10 рабочих потоков для доступа к базе данных.
Это не означает, что вы не должны создавать свои собственные потоки, но есть условия, при которых имеет смысл использовать пул.
Ответ 10
Использование пула - хорошая идея, если вы не знаете или не можете контролировать, сколько потоков будет создано.
Просто у вас возникла проблема с формой, использующей поток, чтобы обновить какое-либо поле из базы данных в событии с позиционированием элемента управления списком (во избежание freez). Потребовалось 5 минут для моего пользователя, чтобы иметь ошибку из базы данных (слишком много связей с Access), потому что он слишком быстро менял позицию списка...
Я знаю, что есть другой способ решить базовую проблему (в том числе не использовать доступ), но пул - хороший старт.