Ein Thread-Pool ist eine Gruppe von vor-instanziierten, inaktiven Threads, die bereit sind, Arbeit zu erhalten. Diese werden der Instanziierung neuer Threads für jede Aufgabe vorgezogen, wenn eine große Anzahl kurzer Aufgaben zu erledigen ist, und nicht eine kleine Anzahl langer. Dies verhindert, dass der Aufwand für das Erstellen eines Threads häufig anfällt.
Die Implementierung variiert je nach Umgebung. Vereinfacht ausgedrückt benötigen Sie jedoch Folgendes:
- Eine Möglichkeit, Threads zu erstellen und im Ruhezustand zu halten. Dies kann erreicht werden, indem jeder Thread an einer Barriere wartet, bis der Pool seine Arbeit abwickelt. (Dies könnte auch mit Mutexen geschehen.)
- Ein Container zum Speichern der erstellten Threads, z. B. eine Warteschlange oder eine andere Struktur, mit der dem Pool ein Thread hinzugefügt und ein Thread herausgezogen werden kann.
- Eine Standardschnittstelle oder abstrakte Klasse für die Threads, die bei der Arbeit verwendet werden sollen. Dies kann eine abstrakte Klasse sein, die
Task
mit einer execute()
Methode aufgerufen wird, die die Arbeit erledigt und dann zurückgibt.
Beim Erstellen des Thread-Pools wird entweder eine bestimmte Anzahl von Threads instanziiert, um verfügbar zu sein, oder je nach den Anforderungen der Implementierung werden neue Threads erstellt.
Wenn der Pool a übergeben wird Task
, nimmt er einen Faden aus dem Container (oder wartet, bis einer verfügbar ist, wenn der Container leer ist), übergibt ihn a Task
und trifft auf die Barriere. Dies führt dazu, dass der inaktive Thread die Ausführung wieder aufnimmt und die execute()
Methode aufruft , mit der Task
er angegeben wurde. Sobald die Ausführung abgeschlossen ist, gibt sich der Thread an den Pool zurück, um zur Wiederverwendung in den Container gelegt zu werden, und trifft dann auf seine Barriere, um sich in den Ruhezustand zu versetzen, bis sich der Zyklus wiederholt.
Der Thread-Pool ist eine Sammlung verwalteter Threads, die normalerweise in einer Warteschlange angeordnet sind und die Aufgaben in der Aufgabenwarteschlange ausführen.
Es ist teuer, jedes Mal ein neues Thread-Objekt zu erstellen, wenn etwas asynchron ausgeführt werden muss. In einem Thread-Pool fügen Sie der Task-Warteschlange einfach die Tasks hinzu, die asynchron ausgeführt werden sollen, und der Thread-Pool übernimmt die Zuweisung eines verfügbaren Threads für die entsprechende Task, sofern vorhanden. Sobald die Aufgabe abgeschlossen ist, fordert der jetzt verfügbare Thread eine andere Aufgabe an (vorausgesetzt, es ist noch eine übrig).
Mit dem Thread-Pool können Sie vermeiden, dass mehr Threads erstellt oder zerstört werden, als wirklich notwendig wären.
Ich würde damit beginnen, eine Klasse mit einer Reihe von Threads und einer Reihe von Aufgaben zu erstellen. Implementieren Sie dann eine Methode, die der Aufgabenwarteschlange eine Aufgabe hinzufügt, und fahren Sie von dort fort. Natürlich sollten Sie es auch ermöglichen, die maximal zulässigen Threads in einem Thread-Pool festzulegen.
quelle
In Multithread-Anwendungen ist der Thread-Pool ein "Pool verfügbarer Threads", der von Ihrer Anwendung verwendet werden kann. In der Regel, z. B. in .NET, wird alles verwaltet, sodass Sie nur Aufgaben zuweisen und sobald ein Thread frei ist, wird er ihn ausführen. Um einen Threadpool zu implementieren, würde ich erwarten, ein Konzept zu erstellen, bei dem Aufgaben automatisch von freien Threads übernommen werden, ohne dass für jede Aufgabe ein expliziter Thread erstellt wird.
quelle
Beispiel aus dem wirklichen Leben;
Sie haben dort eine Einrichtung, in der 12 Personen arbeiten. Es gibt 3 Abschnitte dieser Anlage. Küche, Toiletten und Sicherheit. Wenn Sie keine Thread-Pool-Technik verwenden, funktioniert das so: Alle 12 Personen stehen in einem Besprechungsraum, wenn neue Kunden vor Ort kommen und nach Aufgaben fragen, trennen Sie die Personen in Gruppen und schicken sie zur Arbeit und kommen Sie zurück in den Besprechungsraum. Doch bevor sie ihren Dienst antreten, gibt es eine Vorbereitungsphase. Sie müssen die richtige Uniform tragen, bestimmte Geräte ausrüsten und zu diesem Abschnitt gehen, die Arbeit beenden und zurückkommen. Sobald sie ihre Arbeit beendet haben (Faden endet), müssen sie zurück in den Besprechungsraum gehen, die Uniform ausziehen, die Ausrüstung herausnehmen und auf den nächsten Job warten. Diese beziehen sich auf das Erstellen des Thread-Kontexts, die Speicherzuordnung und die Verfolgung von Informationen durch das Betriebssystem.
Wenn Sie Thread-Pooling verwenden, weisen Sie am frühen Morgen der Küche 6 Personen zu, der Toilette 2 Personen und der Sicherheit 4 Personen. Sie bereiten sich also nur einmal am Tag vor. Auch wenn keine Kunden in der Küche sind, sind diese 4 Personen im Leerlauf für alle anstehenden Aufgaben da. Sie müssen erst wieder in den Besprechungsraum gehen, wenn die Küche geschlossen ist (App endet). Diese 4 Personen befinden sich im Pool der Küchen-App und sind schnell einsatzbereit. Sie können jedoch nicht versprechen, dass sie den ganzen Tag über arbeiten, da die Küche von Zeit zu Zeit inaktiv sein kann. Dieselbe Logik gilt auch für Toiletten und Sicherheit.
Im ersten Szenario verschwenden Sie keinen Thread für eine Aufgabe, ABER es wird viel Zeit in Anspruch nehmen, jeden einzelnen Thread für jede Aufgabe vorzubereiten. In der zweiten Phase bereiten Sie Threads im Voraus vor, sodass Sie nicht garantieren können, dass Sie alle Threads für alle Aufgaben verwenden. Das Betriebssystem optimiert sie jedoch größtenteils, sodass Sie sich auf sie verlassen können.
quelle