Vorwort
Bei der Programmierung mit mehreren Threads ist es unrealistisch, jeder Aufgabe einen Thread zuzuweisen, und der Overhead- und Ressourcenverbrauch der Thread-Erstellung ist sehr hoch. Threadpools entstanden und wurden zu einem leistungsstarken Werkzeug für uns, um Threads zu verwalten. Über die Ausführungsschnittstelle bietet Java eine Standardmethode zum Entkoppeln des Aufgabe -Einreichungsprozesses und zum Ausführen des Prozesses und verwendet Runnable, um die Aufgabe darzustellen.
Anschließend analysieren wir die Implementierung des Java -Thread -Pool -Framework -Threadpoolexecutors.
Die folgende Analyse basiert auf JDK1.7
Lebenszyklus
In ThreadPoolexecutor werden die oberen 3 -Bits der Kapazität verwendet, um den laufenden Zustand darzustellen, nämlich:
1.Running: Erhalten Sie neue Aufgaben und Prozessaufgaben in der Task -Warteschlange
2.Shutdown: Aufgaben, die keine neuen Aufgaben erhalten, sondern Task -Warteschlangen erledigen
3.Stop: Es werden keine neuen Aufgaben empfangen, keine Task -Warteschlange veröffentlicht und alle laufenden Aufgaben werden gleichzeitig unterbrochen
4. Tidying: Alle Aufgaben wurden beendet, die Anzahl der Arbeiterfäden beträgt 0. Wenn dieser Zustand erreicht ist, wird beendet () ausgeführt.
5. Termined: Termined () wurde ausgeführt
Zustandsübergangsdiagramm
Atomklassen werden verwendet, um Staatsbits in ThreadPoolexecutor darzustellen
Private Final Atomicinteger ctl = neuer Atomicinteger (CTLOF (Running, 0));
Thread Poolmodell
Kernparameter
CorepoolSize: Mindestanzahl von lebenden Arbeiterfäden (wenn CALLECORETHREADTimeOut festgelegt ist, dann ist dieser Wert 0)
MaximumphoolSize: Die maximale Anzahl von Threads, durch Kapazität begrenzt
Keepalivetime: Die Überlebenszeit des entsprechenden Fadens, die Zeiteinheit wird durch Zeiteinheit angegeben
WorkQueue: Arbeitswarteschlange, Speichern von Aufgaben, die ausgeführt werden sollen
RejectexecutionHandler: Ablehnung der Richtlinie, die maximale Kapazität des Thread-Pools wird ausgelöst, nachdem der Thread-Pool voll ist: Die ersten drei Kapazitäten werden als Flag-Bits verwendet, dh die maximale Kapazität des Arbeiter-Threads (2^29) -1 ist (2^29) -1
Vier Modelle
CachedThreadpool: Ein zwischengespeicherbarer Fadenpool. Wenn die aktuelle Größe des Thread -Pools die Verarbeitungsanforderungen überschreitet, wird der Leerlauf -Thread recycelt. Wenn die Nachfrage steigt, können neue Threads hinzugefügt werden. Die Größe des Fadenpools ist keine Begrenzung.
FixedThreadpool: Ein Fadenpool mit fester Größe. Bei der Übermittlung einer Aufgabe wird ein Thread erstellt, bis die maximale Anzahl von Threadpools erreicht ist. Zu diesem Zeitpunkt ändert sich die Größe des Fadenpools nicht mehr.
Singlethreadpool: Ein Thread-Pool mit einem Thread, der nur einen Worker-Thread zum Ausführen von Aufgaben hat. Es kann sicherstellen, dass Aufgaben seriell in der Reihenfolge ausgeführt werden, in der sie sich in der Warteschlange befinden. Wenn dieser Thread ungewöhnlich endet, wird ein neuer Thread erstellt, um Aufgaben auszuführen.
ScheduledThreadpool: Ein Threadpool mit fester Größe und führt Aufgaben auf verzögerte oder zeitgesteuerte Weise aus, ähnlich wie der Timer.
Aufgabenausführung ausführen
Kernlogik:
1. Die aktuelle Anzahl der Threads <corepoolSize öffnen direkt den neuen Kern -Thread, um den Aufgabenadworker auszuführen (Befehl, True).
2. Aktuelle Anzahl der Threads> = corepoolSize, und die Aufgabe wird erfolgreich zur Arbeitswarteschlange hinzugefügt
1). Überprüfen Sie, ob sich der aktuelle Status des Thread -Pools im Laufen befindet
2). Wenn nicht, wird die Aufgabe abgelehnt
3). Wenn ja, bestimmen Sie, ob die aktuelle Anzahl der Threads 0 beträgt. Wenn es 0 ist, fügen Sie einen Worker -Thread hinzu.
3. Schalten Sie den normalen Thread Execution Task Addworker (Befehl, Falsch) ein und verweigern Sie die Aufgabe, wenn sie nicht startet. Aus der obigen Analyse können wir die vier Stufen des Thread -Poolbetriebs zusammenfassen:
1) .Poolsize <corepoolSize und die Warteschlange ist leer. Ein neuer Thread wird erstellt, um die eingereichten Aufgaben zu bearbeiten.
2) .PoolSize == CorepoolSize. Zu diesem Zeitpunkt tritt die eingereichte Aufgabe in die Arbeitswarteschlange ein. Der Worker -Thread erhält die Aufgabenausführung aus der Warteschlange. Zu diesem Zeitpunkt ist die Warteschlange nicht leer und nicht voll.
3) .poolsize == corepoolsize und die Warteschlange ist voll. Ein neuer Thread wird auch erstellt, um die eingereichte Aufgabe zu verarbeiten, aber Poolsize <maxpoolsize
4) .PoolSize == MaxpoolSize und die Warteschlange ist voll, die Ablehnungsrichtlinie wird ausgelöst
Ablehnungsrichtlinie <BR /> Wir haben bereits erwähnt, dass eine Aufgabe, wenn sie nicht ausgeführt werden kann, abgelehnt wird. RejectedExecutionHandler ist die Schnittstelle für abgelehnte Aufgaben. Hier sind vier Ablehnungsstrategien.
AbortPolicy: Standardrichtlinie, Aufgabe beenden, Ablehnungsprüfungen werfen
Callerrunspolicy: Führen Sie die aktuelle Aufgabe im Anrufer -Thread aus, ohne Ausnahmen zu werfen
List
Di ScandolderSpolicy: Verlassen Sie die älteste Aufgabe, führen Sie die aktuelle Aufgabe aus und werfen Sie keine Ausnahmen aus
Arbeiter im Threadpool
Der Arbeiter erbt abstraktes Taktequeu -Anchronizer und Runnable. Ersteres bietet dem Arbeiter die Sperrfunktion, und letztere führt die Hauptmethode des Worker -Threads Runworker (Worker W) aus (Snap -Task -Ausführung von Task -Warteschlangen). Arbeiterreferenzen finden Sie in der Arbeitersammlung und sind durch Mainlock geschützt.
Private Final Reentrantlock Mainlock = new Reentrantlock ();
private endgültige Hashset <Anters> Arbeiter = new Hashset <Werbietin> ();
Kernfunktion Runworker
Das Folgende ist die vereinfachte Logik, Anmerkung: Der Auslauf jedes Worker -Threads führt die folgenden Funktionen aus
endgültiger void Runworker (Arbeiter w) {Thread wt = thread.currentThread (); Runnable Task = W.Firsttask; w.firsttask = null; while (task! = null || (task = getTask ())! voranschließend (WT, Aufgabe); task.run (); Nachfolger (Aufgabe, geworfen); W.unlock (); } processWoryRexit (w, abgeschlossen);} 1. Holen Sie sich die Aufgabe von Gettask ()
2. Verschließen Sie den Arbeiter
3. Führen Sie vor dem ausgebildeten (WT, Task) die Erweiterungsmethode aus, die von ThreadPoolexecutor an Unterklassen bereitgestellt wird
4. Führen Sie die Aufgabe aus. Wenn der Arbeiter die erste Aufgabe konfiguriert hat, wird die erste Aufgabe zuerst und nur einmal ausgeführt.
5. Nachfolger nach Ereignis (Aufgabe, geworfen);
6. Schalte den Arbeiter auf
7. Wenn die erhaltene Aufgabe null ist, schließen Sie den Arbeiter
Holen Sie sich die Aufgabe Gettask
Die Task -Warteschlange im Thread -Pool ist eine blockierende Warteschlange, die während des Baus übergeben wird.
Private Final Blockingqueue <Runnable> WorkQueue;
Gettask () erhält die Aufgabe von der Task -Warteschlange und unterstützt das Blockieren und Timeout auf Aufgaben. Vier Situationen führen dazu, dass Null zurückgegeben wird und der Arbeiter geschlossen ist.
1. Die Anzahl der vorhandenen Threads übersteigt die maximale Anzahl von Threads
2. Der Thread -Pool ist im Stoppstaat
3. Der Thread -Pool befindet sich im Stillstand und die Arbeitswarteschlange ist leer
V.
Kernlogik: Timitiert oder blockiert die Warteaufgabe in der blockierenden Warteschlange. Der Zeitpunkt der Warteaufgabe führt dazu, dass der Arbeiter -Thread geschlossen wird.
zeitlich = duldCorethreadTimeout || wc> corepoolsize; runnable r = zeitgesteuert? WorkQueue.poll (Keepalivetime, Timeunit.Nanosekunden): WorkQueue.take ();
Wenn Sie auf eine Aufgabe warten, wird in zwei Fällen einzeitlich:
1. Erlauben Sie den Kernfäden, auf Timeout zu warten, dh erlaubteCoretheadTimeout (true)
2. Der aktuelle Thread ist ein normaler Thread, zu diesem Zeitpunkt WC> Corepoolsize
Die Arbeitskräfte verwendet Blockingqueue, daher werde ich sie hier nicht erweitern. Ich werde später eine detaillierte Analyse schreiben.
Zusammenfassen
ThreadPoolexecutor basiert auf dem Hersteller-Verbrauchermodell. Der Betrieb von Einreichungsaufgaben entspricht dem Produzenten, und der Thread der Ausführung von Aufgaben entspricht dem Verbraucher.
Ausführende bieten vier Methoden zum Konstruktion von Thread -Pool -Modell basierend auf ThreadPoolexecutor. Darüber hinaus können wir ThreadPoolexecutor direkt erben und vorab execute und nachschließenden Methoden umschreiben, um den Thread -Pool -Aufgabenausführungsprozess anzupassen.
Die Verwendung von begrenzten Warteschlangen oder unbegrenzten Warteschlangen muss gemäß der spezifischen Situation berücksichtigt werden, und die Größe der Arbeitswarteschlange und die Anzahl der Threads müssen ebenfalls sorgfältig berücksichtigt werden.
Die Ablehnungsrichtlinie wird empfohlen, Callerrunspolicy zu verwenden, die die Aufgabe nicht aufgibt oder eine Ausnahme ausgelöst hat, sondern die Aufgabe für die Ausführung in den Anrufer -Thread zurückfällt.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.