it-swarm.com.de

Thread vs ThreadPool

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.

130
Mark Ingram

Thread-Pool bietet Vorteile für häufige und relativ kurze Vorgänge von

  • Bereits erstellte Threads wiederverwenden, anstatt neue zu erstellen (ein teurer Prozess)
  • Drosselung der Thread-Erstellungsrate, wenn es eine Flut von Anforderungen für neue Arbeitselemente gibt (ich glaube, dies ist nur in .NET 3.5 der Fall)

    • Wenn Sie 100 Thread-Pool-Tasks 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), und 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 die Erstellung von 100 Threads im Voraus.

    • Wenn in Ihrer Workload regelmäßig eine große Anzahl von Threadpool-Anforderungen eingeht, stellt sich der Threadpool automatisch auf Ihre Workload ein, indem nach dem oben beschriebenen Verfahren mehr Threads im Pool erstellt werden, sodass eine größere Anzahl von Threads für die Verarbeitung von Anforderungen verfügbar ist

    • in hier finden Sie ausführlichere Informationen zur Funktionsweise des Thread-Pools unter der Haube

Es wäre sinnvoller, einen neuen Thread selbst zu erstellen, wenn der Job relativ lange laufen würde (wahrscheinlich ein oder zwei Sekunden, aber dies hängt von der spezifischen Situation ab).

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

105
Karg

Der .NET verwaltete Threadpool: -

  • Die Größe richtet sich nach der aktuellen Arbeitslast und der verfügbaren Hardware
  • Enthält Worker-Threads nd Completion-Port-Threads (die speziell für den Service von E/A verwendet werden)
  • Ist für eine große Anzahl von relativ kurzlebigen Operationen optimiert

Es gibt andere Thread-Pool-Implementierungen, die für lang laufende Vorgänge besser geeignet sind.

Verwenden Sie insbesondere einen Thread-Pool, um zu verhindern, dass Ihre App zu viele 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 mehr Threads zu erzeugen.

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

14
Martin

ebenfalls

new Thread().Start()

spawns Vordergrund-Thread, der nicht stirbt, wenn Sie Ihr Programm schließen. ThreadPool-Threads sind Hintergrund-Threads, die beim Schließen der App abstürzen.

9
Krzysztof

Ich war neugierig auf die relative Ressourcennutzung für diese und führte einen Benchmark auf meinem 2012er Intel i5-Dualcore-Laptop mit .net 4.0-Release unter Windows 8 durch. Die Ausführung von Thread-Pools dauerte durchschnittlich 0,035 ms, wobei Threads durchschnittlich 5,06 benötigten Frau. Mit anderen Worten, der Thread im Pool wurde bei einer großen Anzahl kurzlebiger Threads ca. 300-mal schneller gestartet. Zumindest im getesteten Bereich (100-2000) schien die Gesamtzeit pro Thread ziemlich konstant zu sein.

Dies ist der Code, der getestet wurde:

    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

7
PeterM

Hier nach einem früheren Thread suchen:

Wann sollte ich den ThreadPool nicht in .Net verwenden?

Zusammenfassend lässt sich sagen, dass Threadpool gut ist, wenn Sie viele kurzlebige Threads erzeugen müssen, während Sie mit Threads etwas mehr Kontrolle haben.

3
biozinc

Die Hauptanforderung für die Thread-Pools 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 für Nicht-Kernel-Code nicht geeignet wäre. Ein Hardware-Interrupt-Handler kann jedoch feststellen, dass ein E/A-Beendigungs-Rückruf im Benutzermodus so bald wie möglich ausgeführt werden sollte. Einen neuen Thread zu erstellen, um so etwas laufen zu lassen, wäre ein gewaltiger Overkill. Ein paar vorab erstellte Threads, die zum Ausführen von E/A-Beendigungs-Rückrufen oder ähnlichen Dingen abgesetzt werden können, sind wesentlich effizienter.

Ein Schlüsselaspekt solcher Threads ist, dass, wenn E/A-Beendigungsmethoden immer im Wesentlichen sofort abgeschlossen und niemals blockiert werden und die Anzahl solcher Threads, die derzeit solche Methoden ausführen, mindestens der Anzahl der Prozessoren entspricht, der einzige Weg, den ein anderer Thread geht 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; Keines davon sollte sehr oft vorkommen, wenn der Thread-Pool bestimmungsgemäß verwendet wird.

Wenn nicht zu erwarten ist, dass eine Methode innerhalb von ca. 100 ms nach dem Start der Ausführung beendet wird, sollte die Methode auf andere Weise als über den Hauptthreadpool ausgeführt werden. Wenn eine Vielzahl von Aufgaben zu erledigen ist, die viel CPU beanspruchen, aber nicht blockiert werden, kann es hilfreich sein, sie unter Verwendung eines Pools von Anwendungsthreads (einer pro CPU-Kern) zu verteilen, der vom "Haupt" -Threadpool getrennt ist, da verwendet Mehr Threads als Kerne sind kontraproduktiv, wenn nicht blockierende CPU-intensive Tasks 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 und mit ziemlicher Sicherheit nicht in einem Hauptthreadpool-Thread ausgeführt werden. Wenn eine Operation mit langer Laufzeit durch einen E/A-Rückruf ausgelöst werden soll, sollte entweder vor dem Rückruf ein Thread für die Operation mit langer Laufzeit gestartet und auf einem Monitor gewartet werden, der vom Rückruf gepulst wird Lassen Sie den Rückruf einen neuen Thread starten, um den Vorgang auszuführen, während der Rückruf beendet wird, und seinen eigenen Thread effektiv an den Threadpool zurückzugeben.

1
supercat

Thread-lokaler Speicher ist bei Thread-Pools keine gute Idee. Es gibt Fäden eine "Identität"; Nicht mehr alle Themen 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 auszuführen.

1
MSalters

Wenn Sie viele Threads benötigen, möchten Sie wahrscheinlich einen ThreadPool verwenden. Sie verwenden Threads erneut, um den Aufwand für die Thread-Erstellung zu verringern.

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

1
Rob Prouse

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 Thread verwendet, um ein Feld aus einer Datenbank bei einem positionsveränderten Ereignis eines Listensteuerelements zu aktualisieren (vermeiden Sie Freez). 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 des Nichtverwendens von Zugriff), aber Pooling ist ein guter Anfang.

0
Marco Guignard

Im Allgemeinen (ich habe .NET noch nie verwendet) würde ein Thread-Pool für Ressourcenverwaltungszwecke verwendet. Hiermit können Einschränkungen in Ihrer Software konfiguriert werden. Dies kann auch aus Gründen der Leistung erfolgen, da die Erstellung neuer Threads unter Umständen kostspielig ist.

Es kann auch systemspezifische Gründe geben. In Java (ich weiß auch nicht, ob dies für .NET gilt) wendet der Manager der Threads möglicherweise threadspezifische Variablen an, wenn jeder Thread aus dem Pool gezogen wird, und deaktiviert sie, wenn sie zutreffen zurückgegeben werden (üblicher Weg, um so etwas wie eine Identität zu übergeben).

Beispielbedingung: 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 die Verwendung eines Pools sinnvoll ist.

0
Robin