回答:
スレッドプールは、頻繁で比較的短い操作に利点を提供します
新しい作業項目の要求が急増した場合にスレッド作成の速度を調整する(これは.NET 3.5のみにあると思います)
100個のスレッドプールタスクをキューに入れると、これらの要求を処理するためにすでに作成されているスレッドだけが使用されます(たとえば10個)。スレッドプールは頻繁にチェックし(3.5 SP1では500ミリ秒ごとと考えています)、キューに入れられたタスクがある場合、新しいスレッドを1つ作成します。タスクが速い場合、新しいスレッドの数は少なくなり、10個ほどの短いタスクのスレッドを再利用すると、100個のスレッドを事前に作成するよりも速くなります。
ワークロードに一貫して多数のスレッドプール要求が入ってくる場合、スレッドプールは、上記のプロセスによってプール内により多くのスレッドを作成することにより、ワークロードに自動調整され、要求の処理に使用できるスレッドの数が多くなります。
スレッドプールが内部でどのように機能するかについての詳細は、ここをチェックしてください
ジョブが比較的長く実行される場合は、自分で新しいスレッドを作成する方が適切です(おそらく1〜2秒程度ですが、特定の状況によって異なります)。
@Krzysztof-スレッドプールスレッドは、メインスレッドが終了すると停止するバックグラウンドスレッドです。手動で作成されたスレッドはデフォルトでフォアグラウンドです(メインスレッドが終了した後も実行を継続します)が、Startを呼び出す前にバックグラウンドに設定できます。
.NET管理のスレッドプール:-
長時間実行される操作により適している可能性のある他のスレッドプール実装があります。
具体的には、スレッドプールを使用して、アプリが作成するスレッドが多すぎないようにします。スレッドプールの最も重要な機能は作業キューです。つまり、マシンが十分にビジーになると、スレッドプールはすぐに追加のスレッドを生成するのではなく、要求をキューに入れます。
したがって、少数の限られた数のスレッドを作成する場合は、自分で作成します。作成される可能性のあるスレッドの数を事前に決定できず(たとえば、受信IOに応答して作成される)、それらの作業が短命になる場合は、スレッドプールを使用します。数がわからなくても、作業に時間がかかる場合は、プラットフォームに役立つものはありませんが、適合する別のスレッドプール実装を見つけることができる場合があります。
また
new Thread().Start()
プログラムを閉じても死ぬことのないフォアグラウンドスレッドを生成します。ThreadPoolスレッドは、アプリを閉じるときに終了するバックグラウンドスレッドです。
私はこれらの相対的なリソース使用量に興味があり、Windows 8で.net 4.0リリースビルドを使用して2012年のデュアルコアインテルi5ラップトップでベンチマークを実行しました。スレッドプールが開始するのに平均0.035msかかりましたMS。つまり、プール内のスレッドは、多数の短期間のスレッドに対して約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();
}
以前のスレッドについては、こちらを確認してください:
.NetでThreadPoolを使用すべきでないのはいつですか?
要約すると、短期間のスレッドを多数生成する必要がある場合はThreadpoolが適していますが、Threadsを使用すると、もう少し制御が容易になります。
adpoolスレッドの主な必要性は、ほぼ瞬時に完了することが予想される短い小さなタスクを処理することです。ハードウェア割り込みハンドラーは、非カーネルコードに適さないスタッキングコンテキストで実行されることがよくありますが、ハードウェア割り込みハンドラーは、ユーザーモードI / O完了コールバックをできるだけ早く実行する必要があることを検出する場合があります。そのようなことを実行する目的で新しいスレッドを作成することは、大げさすぎるでしょう。I / O完了コールバックまたは他の同様のものを実行するためにディスパッチできるいくつかの事前に作成されたスレッドがあると、はるかに効率的です。
そのようなスレッドの重要な側面は、I / O完了メソッドが常に本質的に瞬時に完了し、ブロックされない場合、そのようなメソッドを現在実行しているスレッドの数が少なくともプロセッサの数と等しい場合、他のスレッドの唯一の方法です。前述のメソッドのいずれかが終了する前に、他のメソッドのいずれかがブロックするか、その実行時間が通常のスレッド化タイムスライスを超える場合に実行できます。スレッドプールが意図したとおりに使用されている場合、どちらも頻繁に発生することはありません。
メソッドの実行開始から100ms以内に終了することが期待できない場合は、メインスレッドプール以外の方法でメソッドを実行する必要があります。CPUを集中的に使用するがブロックされない多くのタスクを実行する場合、「メイン」スレッドプールとは別のアプリケーションスレッドのプール(CPUコアごとに1つ)を使用してそれらをディスパッチすると役立つ場合があります。 CPUを集中的に使用しないタスクを実行する場合、コアよりも多くのスレッドは逆効果になります。ただし、メソッドの実行に1秒以上かかり、ほとんどの時間をブロックする場合は、メソッドを専用スレッドで実行する必要があり、メインスレッドプールスレッドでは実行しないでください。I / Oコールバックなどによって長時間実行される操作をトリガーする必要がある場合は、
一般に(私は.NETを使用したことがありません)、スレッドプールはリソース管理の目的で使用されます。ソフトウェアに制約を設定することができます。新しいスレッドの作成にはコストがかかる可能性があるため、パフォーマンス上の理由から行われることもあります。
システム固有の理由もあります。Javaでは(これも.NETに当てはまるかどうかはわかりません)、スレッドのマネージャーは、各スレッドがプールからプルされるときにスレッド固有の変数を適用し、返されたときにそれらを設定解除します(次のようなものを渡す一般的な方法)アイデンティティ)。
制約の例:データベース接続が10しかないため、データベースへのアクセスには10ワーカースレッドしか許可しません。
これは、独自のスレッドを作成するべきではないという意味ではありませんが、プールを使用することが理にかなっている条件があります。
スレッド:
スレッドプール: