Thread gegen ThreadPool

137

Was ist der Unterschied zwischen der Verwendung eines neuen Threads und der Verwendung eines Threads aus dem Thread-Pool? Welche Leistungsvorteile gibt es und warum sollte ich in Betracht ziehen, einen Thread aus dem Pool zu verwenden, anstatt einen, den ich explizit erstellt habe? Ich denke hier speziell an .NET, aber allgemeine Beispiele sind in Ordnung.

Mark Ingram
quelle

Antworten:

110

Der Thread-Pool bietet Vorteile für häufige und relativ kurze Operationen von

  • Wiederverwenden bereits erstellter Threads anstelle neuer Threads (ein teurer Prozess)
  • Drosselung der Geschwindigkeit der Thread-Erstellung, wenn eine Reihe von Anforderungen für neue Arbeitselemente auftreten (ich glaube, dies ist nur in .NET 3.5 möglich).

    • Wenn Sie 100 Thread-Pool-Aufgaben in die Warteschlange stellen, werden nur so viele Threads verwendet, wie bereits erstellt wurden, um diese Anforderungen zu bearbeiten (z. B. 10). Der Thread-Pool führt häufige Überprüfungen durch (ich glaube alle 500 ms in 3.5 SP1). Wenn sich Aufgaben in der Warteschlange befinden, wird ein neuer Thread erstellt. Wenn Ihre Aufgaben schnell sind, ist die Anzahl der neuen Threads gering und die Wiederverwendung der etwa 10 Threads für die kurzen Aufgaben ist schneller als das Erstellen von 100 Threads im Voraus.

    • Wenn in Ihrer Workload konsistent eine große Anzahl von Thread-Pool-Anforderungen eingeht, passt sich der Thread-Pool an Ihre Workload an, indem durch den obigen Prozess mehr Threads im Pool erstellt werden, sodass eine größere Anzahl von Threads für die Verarbeitung von Anforderungen verfügbar ist

    • Check hier für mehr in der Tiefen Informationen darüber , wie die Thread - Pool - Funktionen unter der Haube

Das Erstellen eines neuen Threads selbst wäre angemessener, wenn der Job relativ lange dauern würde (wahrscheinlich ein oder zwei Sekunden, aber dies hängt von der jeweiligen Situation ab).

@Krzysztof - Thread-Pool-Threads sind Hintergrund-Threads, die beendet werden, wenn der Haupt-Thread endet. Manuell erstellte Threads stehen standardmäßig im Vordergrund (werden nach dem Ende des Hauptthreads weiter ausgeführt), können jedoch vor dem Aufruf von Start auf Hintergrund gesetzt werden.

Karg
quelle
5
Das einzige, worüber ich mich wundere, ist die folgende Anweisung von MSDN ( msdn.microsoft.com/en-us/library/1c9txz50.aspx ) "Ein Hintergrundthread wird nur ausgeführt, wenn die Anzahl der ausgeführten Vordergrundthreads kleiner als die Anzahl der Prozessoren ist . ". Bedeutet das also, dass bei der Aufteilung der Arbeit auf Kerne Vordergrund-Threads Vorrang haben?
Cdiggins
1
➤ Sie können einen Thread aus dem Thread-Pool nicht abbrechen oder unterbrechen. ➤ Sie können keinen Thread aus dem Thread-Pool verbinden. Um dies zu erreichen, müssen Sie einige andere Mechanismen verwenden
Zinov
14

Der von .NET verwaltete Threadpool: -

  • Größe selbst basierend auf der aktuellen Arbeitslast und der verfügbaren Hardware
  • Enthält Worker-Threads und Completion-Port-Threads (die speziell für die Wartung von E / A verwendet werden).
  • Ist für eine Vielzahl von relativ kurzlebigen Operationen optimiert

Es gibt andere Thread-Pool-Implementierungen, die für länger laufende Vorgänge möglicherweise besser geeignet sind.

Verwenden Sie insbesondere einen Thread-Pool, um zu verhindern, dass Ihre App zu viele erstellt Threads erstellt. Das wichtigste Merkmal eines Threadpools ist die Arbeitswarteschlange. Das heißt, sobald Ihr Computer ausreichend ausgelastet ist, stellt der Threadpool Anforderungen in die Warteschlange, anstatt sofort weitere Threads zu erzeugen.

Wenn Sie also eine kleine, begrenzte Anzahl von Threads erstellen, erstellen Sie diese selbst. Wenn Sie im Voraus nicht bestimmen können, wie viele Threads möglicherweise erstellt werden (z. B. als Reaktion auf eingehende E / A), und ihre Arbeit nur von kurzer Dauer ist, verwenden Sie den Threadpool. Wenn Sie nicht wissen, wie viele, aber ihre Arbeit wird lange dauern, gibt es auf der Plattform nichts, was Ihnen helfen könnte - aber Sie können möglicherweise alternative Threadpool-Implementierungen finden, die passen.

Martin
quelle
Können Sie in .NET Abschlussports ohne den Thread-Pool verwenden? Ich ging davon aus, dass die asynchronen E / A-Methoden der einzige Weg waren (in .NET) und dass sie den Thread-Pool verwenden
Karg
10

ebenfalls

new Thread().Start()

erzeugt einen Vordergrund-Thread, der nicht stirbt, wenn Sie Ihr Programm schließen. ThreadPool-Threads sind Hintergrund-Threads, die beim Schließen der App absterben.


quelle
11
Sie können jederzeit einen Thread auf Hintergrund setzen. Sie stehen standardmäßig nur im Vordergrund.
Kris Erickson
3
nemo: var t = neuer Thread (...); t.BackgroundThread = true; t.Start ();
Ricardo Amores
18
Klarstellung zum Begriff "Programm". Eine Desktop-Anwendung wird in einem Prozess ausgeführt und verfügt über mindestens einen Vordergrund-Thread, der die Benutzeroberfläche verwaltet. Dieser Prozess wird so lange ausgeführt, wie er über Vordergrund-Threads verfügt. Wenn Sie eine Desktop-Anwendung schließen, wird der Vordergrund-UI-Thread gestoppt , aber Sie haben den Prozess nicht unbedingt gestoppt, wenn er andere Vordergrund-Threads enthält.
G-Wiz
8

Ich war neugierig auf die relative Ressourcennutzung für diese und führte einen Benchmark auf meinem 2012 Dual-Core-Intel i5-Laptop mit .net 4.0-Release auf Windows 8 durch. Thread-Pools dauerten durchschnittlich 0,035 ms, um dort zu starten, wo Threads durchschnittlich 5,06 nahmen Frau. Mit anderen Worten, der Thread im Pool wurde für eine große Anzahl kurzlebiger Threads etwa 300-mal schneller gestartet. Zumindest in den getesteten Threads (100-2000) schien die Gesamtzeit pro Thread ziemlich konstant zu sein.

Dies ist der Code, der bewertet wurde:

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

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

Geben Sie hier die Bildbeschreibung ein

PeterM
quelle
5
Ich denke, es liegt daran, dass der ThreadPool die erstellten Threads wiederverwendet, anstatt neue zu erstellen (was sehr teuer ist)
Fabriciorissetto
1

Lokaler Thread-Speicher ist bei Thread-Pools keine gute Idee. Es gibt Threads eine "Identität"; Nicht mehr alle Threads sind gleich. Jetzt sind Thread-Pools besonders nützlich, wenn Sie nur eine Reihe identischer Threads benötigen, die bereit sind, Ihre Arbeit ohne Erstellungsaufwand zu erledigen.

MSalters
quelle
1

Wenn Sie viele Threads benötigen, möchten Sie wahrscheinlich einen ThreadPool verwenden. Sie verwenden Threads wieder, wodurch Sie den Aufwand für die Thread-Erstellung sparen.

Wenn Sie nur einen Thread benötigen, um etwas zu erledigen, ist Thread wahrscheinlich am einfachsten.

Rob Prouse
quelle
1

Der Hauptbedarf für Theadpool-Threads besteht darin, kurze kleine Aufgaben zu erledigen, von denen erwartet wird, dass sie fast sofort erledigt werden. Hardware-Interrupt-Handler werden häufig in einem Stapelkontext ausgeführt, der nicht für Nicht-Kernel-Code geeignet ist. Ein Hardware-Interrupt-Handler kann jedoch feststellen, dass ein Rückruf zum Abschluss der E / A im Benutzermodus so bald wie möglich ausgeführt werden sollte. Das Erstellen eines neuen Threads zum Ausführen eines solchen Dings wäre ein massiver Overkill. Es ist viel effizienter, einige vorab erstellte Threads zu haben, die zum Ausführen von E / A-Abschlussrückrufen oder ähnlichen Dingen gesendet werden können.

Ein Schlüsselaspekt solcher Threads ist, dass, wenn E / A-Abschlussmethoden immer im Wesentlichen sofort abgeschlossen werden und niemals blockiert werden und die Anzahl solcher Threads, auf denen solche Methoden derzeit ausgeführt werden, mindestens der Anzahl der Prozessoren entspricht, der einzige Weg für jeden anderen Thread ist könnte ausgeführt werden, bevor eine der oben genannten Methoden beendet ist, wenn eine der anderen Methoden blockiert oder ihre Ausführungszeit eine normale Threading-Zeitscheibe überschreitet; Beides sollte nicht sehr oft vorkommen, wenn der Thread-Pool wie vorgesehen verwendet wird.

Wenn nicht erwartet werden kann, dass eine Methode innerhalb von etwa 100 ms nach Beginn der Ausführung beendet wird, sollte die Methode auf andere Weise als über den Hauptthreadpool ausgeführt werden. Wenn viele Aufgaben ausgeführt werden müssen, die CPU-intensiv sind, aber nicht blockiert werden, kann es hilfreich sein, sie mithilfe eines Pools von Anwendungsthreads (einer pro CPU-Kern) zu versenden, der seit der Verwendung vom "Haupt" -Threadpool getrennt ist Mehr Threads als Kerne sind kontraproduktiv, wenn nicht blockierende CPU-intensive Aufgaben ausgeführt werden. Wenn die Ausführung einer Methode jedoch eine Sekunde oder länger dauert und die meiste Zeit blockiert ist, sollte die Methode wahrscheinlich in einem dedizierten Thread ausgeführt werden und mit ziemlicher Sicherheit nicht in einem Haupt-Threadpool-Thread. Wenn ein lang laufender Vorgang durch einen E / A-Rückruf ausgelöst werden muss,

Superkatze
quelle
0

Im Allgemeinen (ich habe .NET noch nie verwendet) wird ein Thread-Pool für Ressourcenverwaltungszwecke verwendet. Hiermit können Einschränkungen in Ihrer Software konfiguriert werden. Dies kann auch aus Leistungsgründen erfolgen, da das Erstellen neuer Threads kostspielig sein kann.

Es kann auch systemspezifische Gründe geben. In Java (wieder weiß ich nicht, ob dies für .NET gilt) kann der Manager der Threads threadspezifische Variablen anwenden, wenn jeder Thread aus dem Pool gezogen wird, und sie deaktivieren, wenn sie zurückgegeben werden (übliche Methode, um so etwas zu übergeben eine Identität).

Beispieleinschränkung: Ich habe nur 10 Datenbankverbindungen, daher würde ich nur 10 Arbeitsthreads für den Zugriff auf die Datenbank zulassen.

Dies bedeutet nicht, dass Sie keine eigenen Threads erstellen sollten, aber es gibt Bedingungen, unter denen es sinnvoll ist, einen Pool zu verwenden.

Robin
quelle
0

Die Verwendung eines Pools ist eine gute Idee, wenn Sie nicht wissen oder nicht steuern können, wie viele Threads erstellt werden.

Haben Sie nur ein Problem mit einem Formular, das einen Thread verwendet, um ein Feld aus einer Datenbank bei einem Ereignis mit Positionsänderung eines Listensteuerelements zu aktualisieren (Einfrieren vermeiden). Es dauerte 5 Minuten, bis mein Benutzer einen Fehler in der Datenbank hatte (zu viele Verbindungen mit Access), weil er die Listenposition zu schnell änderte ...

Ich weiß, dass es eine andere Möglichkeit gibt, das Basisproblem zu lösen (einschließlich der Nichtverwendung des Zugriffs), aber Pooling ist ein guter Anfang.

Marco Guignard
quelle
0

Thread :

  1. Das Erstellen eines Threads ist weitaus langsamer als die Verwendung des Thread-Pools.
  2. Sie können die Priorität eines Threads ändern.
  3. Die maximale Anzahl von Threads in einem Prozess, die sich auf Ressourcen beziehen.
  4. Der Thread befindet sich auf Betriebssystemebene und wird vom Betriebssystem gesteuert.
  5. Die Verwendung von Thread ist eine bessere Option, wenn die Aufgabe relativ lange dauert

Thread-Pool :

  1. Das Ausführen eines Threads im Thread-Pool ist weitaus schneller als das direkte Erstellen eines Threads.
  2. Sie können die Priorität eines Thread-Laufs basierend auf dem Thread-Pool nicht ändern.
  3. Es gibt nur einen Thread-Pool pro Prozess.
  4. Der Thread-Pool wird von CLR verwaltet.
  5. Der Thread-Pool ist nützlich für den kurzlebigen Betrieb.
  6. Die Anzahl der Threads im Thread-Pool hängt von der Anwendungslast ab.
  7. TPL-Tasks werden basierend auf dem Thread-Pool ausgeführt
Seyedraouf Modarresi
quelle