スレッドとThreadPool


137

新しいスレッドの使用とスレッドプールのスレッドの使用の違いは何ですか?パフォーマンス上の利点は何ですか。また、明示的に作成したスレッドではなく、プールのスレッドの使用を検討する必要があるのはなぜですか。ここでは特に.NETについて考えていますが、一般的な例は問題ありません。

回答:


110

スレッドプールは、頻繁で比較的短い操作に利点を提供します

  • 新しいスレッドを作成する代わりに、作成済みのスレッドを再利用する(コストのかかるプロセス)
  • 新しい作業項目の要求が急増した場合にスレッド作成の速度を調整する(これは.NET 3.5のみにあると思います)

    • 100個のスレッドプールタスクをキューに入れると、これらの要求を処理するためにすでに作成されているスレッドだけが使用されます(たとえば10個)。スレッドプールは頻繁にチェックし(3.5 SP1では500ミリ秒ごとと考えています)、キューに入れられたタスクがある場合、新しいスレッドを1つ作成します。タスクが速い場合、新しいスレッドの数は少なくなり、10個ほどの短いタスクのスレッドを再利用すると、100個のスレッドを事前に作成するよりも速くなります。

    • ワークロードに一貫して多数のスレッドプール要求が入ってくる場合、スレッドプールは、上記のプロセスによってプール内により多くのスレッドを作成することにより、ワークロードに自動調整され、要求の処理に使用できるスレッドの数が多くなります。

    • スレッドプールが内部でどのように機能するかについての詳細は、ここをチェックしてください

ジョブが比較的長く実行される場合は、自分で新しいスレッドを作成する方が適切です(おそらく1〜2秒程度ですが、特定の状況によって異なります)。

@Krzysztof-スレッドプールスレッドは、メインスレッドが終了すると停止するバックグラウンドスレッドです。手動で作成されたスレッドはデフォルトでフォアグラウンドです(メインスレッドが終了した後も実行を継続します)が、Startを呼び出す前にバックグラウンドに設定できます。


5
私が不思議に思っているのは、MSDNからの次のステートメント(msdn.microsoft.com/en-us/library/1c9txz50.aspx)です。 ……」つまり、コア間で作業を分割するときに、フォアグラウンドスレッドが優先されるということですか。
cdiggins 2010

1
threadスレッドプールからスレッドを中止または中断することはできません。threadスレッドプールからスレッドに参加することはできません。それを達成するには、いくつかの他のメカニズムを使用する必要があります
Zinov

14

.NET管理のスレッドプール:-

  • 現在のワークロードと利用可能なハードウェアに基づいてサイズを決定します
  • ワーカースレッド完了ポートスレッドが含まれます(これらは特にIOのサービスに使用されます)
  • 比較的短期間の多数の操作に最適化されています

長時間実行される操作により適している可能性のある他のスレッドプール実装があります。

具体的には、スレッドプールを使用して、アプリが作成するスレッドが多すぎないようにします。スレッドプールの最も重要な機能は作業キューです。つまり、マシンが十分にビジーになると、スレッドプールはすぐに追加のスレッドを生成するのではなく、要求をキューに入れます。

したがって、少数の限られた数のスレッドを作成する場合は、自分で作成します。作成される可能性のあるスレッドの数を事前に決定できず(たとえば、受信IOに応答して作成される)、それらの作業が短命になる場合は、スレッドプールを使用します。数がわからなくても、作業に時間がかかる場合は、プラットフォームに役立つものはありませんが、適合する別のスレッドプール実装を見つけることができる場合があります。


.NETでは、スレッドプールなしで完了ポートを使用できますか?私は、非同期I / Oメソッドが(.NETで)唯一の方法であり、スレッドプールを使用するという仮定の下にありました
Karg

10

また

new Thread().Start()

プログラムを閉じても死ぬことのないフォアグラウンドスレッドを生成します。ThreadPoolスレッドは、アプリを閉じるときに終了するバックグラウンドスレッドです。


11
スレッドはいつでも背景に設定できます。デフォルトでは、これらはフォアグラウンドです。
クリスエリクソン

3
nemo:var t = new Thread(...); t.BackgroundThread = true; t.Start();
Ricardo Amores、

18
「プログラム」という用語に関する説明。デスクトップアプリケーションはプロセス内で実行され、UIを管理する少なくとも1つのフォアグラウンドスレッドを持っています。フォアグラウンドスレッドがある限り、そのプロセスは実行を続けます。デスクトップアプリケーションを閉じると、フォアグラウンドUIスレッドは停止しますが、他のフォアグラウンドスレッドがある場合必ずしもプロセスを停止しているわけではありません。
G-Wiz 2010年

8

私はこれらの相対的なリソース使用量に興味があり、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();
    }

ここに画像の説明を入力してください


5
ThreadPoolは、新しいスレッドを作成するのではなく、作成されたスレッドを再利用するためだと思います(かなり高価です)
fabriciorissetto


1

スレッドローカルストレージは、スレッドプールでは適切ではありません。スレッドに「アイデンティティ」を与えます。すべてのスレッドが同じであるとは限りません。スレッドプールは、同一のスレッドの束だけが必要で、作成のオーバーヘッドなしで作業を行う準備ができている場合に特に便利です。


1

多数のスレッドが必要な場合は、おそらくThreadPoolを使用します。スレッドを再利用して、スレッド作成のオーバーヘッドを削減します。

何かを実行するために1つのスレッドが必要な場合は、おそらくスレッドが最も簡単です。


1

adpoolスレッドの主な必要性は、ほぼ瞬時に完了することが予想される短い小さなタスクを処理することです。ハードウェア割り込みハンドラーは、非カーネルコードに適さないスタッキングコンテキストで実行されることがよくありますが、ハードウェア割り込みハンドラーは、ユーザーモードI / O完了コールバックをできるだけ早く実行する必要があることを検出する場合があります。そのようなことを実行する目的で新しいスレッドを作成することは、大げさすぎるでしょう。I / O完了コールバックまたは他の同様のものを実行するためにディスパッチできるいくつかの事前に作成されたスレッドがあると、はるかに効率的です。

そのようなスレッドの重要な側面は、I / O完了メソッドが常に本質的に瞬時に完了し、ブロックされない場合、そのようなメソッドを現在実行しているスレッドの数が少なくともプロセッサの数と等しい場合、他のスレッドの唯一の方法です。前述のメソッドのいずれかが終了する前に、他のメソッドのいずれかがブロックするか、その実行時間が通常のスレッド化タイムスライスを超える場合に実行できます。スレッドプールが意図したとおりに使用されている場合、どちらも頻繁に発生することはありません。

メソッドの実行開始から100ms以内に終了することが期待できない場合は、メインスレッドプール以外の方法でメソッドを実行する必要があります。CPUを集中的に使用するがブロックされない多くのタスクを実行する場合、「メイン」スレッドプールとは別のアプリケーションスレッドのプール(CPUコアごとに1つ)を使用してそれらをディスパッチすると役立つ場合があります。 CPUを集中的に使用しないタスクを実行する場合、コアよりも多くのスレッドは逆効果になります。ただし、メソッドの実行に1秒以上かかり、ほとんどの時間をブロックする場合は、メソッドを専用スレッドで実行する必要があり、メインスレッドプールスレッドでは実行しないでください。I / Oコールバックなどによって長時間実行される操作をトリガーする必要がある場合は、


0

一般に(私は.NETを使用したことがありません)、スレッドプールはリソース管理の目的で使用されます。ソフトウェアに制約を設定することができます。新しいスレッドの作成にはコストがかかる可能性があるため、パフォーマンス上の理由から行われることもあります。

システム固有の理由もあります。Javaでは(これも.NETに当てはまるかどうかはわかりません)、スレッドのマネージャーは、各スレッドがプールからプルされるときにスレッド固有の変数を適用し、返されたときにそれらを設定解除します(次のようなものを渡す一般的な方法)アイデンティティ)。

制約の例:データベース接続が10しかないため、データベースへのアクセスには10ワーカースレッドしか許可しません。

これは、独自のスレッドを作成するべきではないという意味ではありませんが、プールを使用することが理にかなっている条件があります。


0

作成されるスレッドの数がわからない、または制御できない場合は、プールを使用することをお勧めします。

スレッドを使用して、リストコントロールのpositionchangedイベントでデータベースの一部のフィールドを更新するフォームに問題があるだけです(freezは避けてください)。ユーザーがリストの位置を変更する速度が速すぎたため、ユーザーがデータベースからエラー(Accessとの接続が多すぎる)になるのに5分かかりました...

基本的な問題(アクセスを使用しないことを含む)を解決する他の方法があることは知っていますが、プールは良い出発点です。


0

スレッド

  1. スレッドの作成は、スレッドプールを使用するよりもはるかに低速です。
  2. スレッドの優先順位を変更できます。
  3. リソースに関連するプロセス内のスレッドの最大数。
  4. スレッドはOSレベルであり、OSによって制御されます。
  5. スレッドの使用は、タスクの実行時間が比較的長い場合に適しています。

スレッドプール

  1. スレッドプールでスレッドを実行すると、直接スレッドを作成するよりもはるかに高速です。
  2. スレッドプールに基づいて実行されるスレッドの優先順位を変更することはできません。
  3. プロセスごとにスレッドプールは1つだけです。
  4. スレッドプールはCLRによって管理されます。
  5. スレッドプールは、短期間の運用に役立ちます。
  6. スレッドプール内のスレッドの数は、アプリケーションの負荷に関連しています。
  7. TPLタスクはスレッドプールに基づいて実行されます
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.