Ab Java 5 bietet Java einen eigenen Thread -Pool. Ein Threadpool ist ein Threadbehälter, der nur eine Nennzahl von Threads gleichzeitig ausführt. java.util.concurrent.threadpoolexecutor ist ein solcher Thread -Pool. Es ist sehr flexibel, aber auch kompliziert zu verwenden, sodass dieser Artikel es vorstellt.
Erstens ist der Konstruktor. Nehmen Sie den einfachsten Konstruktor als Beispiel:
Public ThreadPoolexecutor (int corepoolsize, int maximumpoolsize, langwächstes Keepalivetime, Timeunit -Einheit, Blockingqueue <Runnable> WorkQueue)
Es sieht ziemlich kompliziert aus. Lassen Sie mich es hier vorstellen.
Corepoolsize bezieht sich auf die reservierte Gewindepoolgröße.
Maximumpoolsize bezieht sich auf die maximale Größe des Fadenpools.
Keepalivetime bezieht sich auf die Zeitüberschreitung, in der der Leerlauffaden endet.
Die Einheit ist eine Aufzählung, die die Einheit der Keepalivetime darstellt.
WorkQueue repräsentiert die Warteschlange für die Aufbewahrung von Aufgaben.
Wir können die Bedeutung dieser Parameter aus dem Arbeitsprozess des Threadpools verstehen. Der Arbeitsprozess des Thread -Pools lautet wie folgt:
1. Als der Thread -Pool zum ersten Mal erstellt wurde, gab es keinen Faden im Inneren. Die Task -Warteschlange wird als Parameter übergeben. Selbst wenn in der Warteschlange Aufgaben vorhanden sind, führt der Thread -Pool sie nicht sofort aus.
2. Bei der Aufrufen von Execute () -Methoden zum Hinzufügen einer Aufgabe fällt der Thread -Pool das folgende Urteil:
a.
b.
c.
d.
3. Wenn ein Thread eine Aufgabe erledigt, wird von der Warteschlange ausgeführt.
4. Wenn ein Thread nichts zu tun hat und es eine gewisse Zeit dauert (Keepalivetime), wird der Thread -Pool beurteilt, dass der Thread gestoppt wird, wenn die Anzahl der derzeit ausgeführten Threads größer ist als Corepoolsize. Nachdem alle Aufgaben des Fadenpools erledigt sind, schrumpfen er schließlich auf die Größe von Corepoolsize.
Dieser Vorgang zeigt, dass es nicht erforderlich ist, die Aufgabe zuerst auszuführen, wenn Sie zuerst der Aufgabe anschließen. Unter der Annahme, dass die Warteschlangengröße 10 beträgt, ist Corepoolsize 3 und Maximumphoolsize 6. Wenn 20 Aufgaben hinzugefügt werden, ist die Ausführungsreihenfolge wie folgt: Erstens werden die Aufgaben 1, 2, 3 ausgeführt und dann werden Aufgaben 4 ~ 13 platziert in der Warteschlange. Zu diesem Zeitpunkt ist die Warteschlange voll, die Aufgaben 14, 15, 16 werden sofort ausgeführt, und die Aufgaben von 17 ~ 20 werden Ausnahmen werfen. Die endgültige Ordnung ist: 1, 2, 3, 14, 15, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13. Hier ist ein Beispiel für die Verwendung von Thread -Poolen:
public static void main (String [] args) {BlockingQueue <Runnable> Queue = New Linked BlockingQueue <Runnable> (); 0; i <20; out.
Eine Erklärung dieses Beispiels ist wie folgt:
1. Blockingqueue ist nur eine Schnittstelle. Der Vorteil der Verwendung von Linked Blockingqueue besteht darin, dass es keine Größengrenze gibt. Da die Warteschlange nicht voll ist, wird execute () keine Ausnahme auswerfen und die Anzahl der im Thread -Pool ausgeführten Threads wird Corepoolsize niemals überschreiten, sodass der Parameter von Keepalivetime bedeutungslos ist.
2. Die Shutdown () -Methode blockiert nicht. Nach dem Aufrufen der Shutdown () -Methode endet der Hauptfaden sofort und der Thread -Pool wird weiter ausgeführt, bis alle Aufgaben vor dem Stoppen ausgeführt werden. Wenn die Shutdown () -Methode nicht aufgerufen wird, bleibt der Thread -Pool so, dass jederzeit neue Aufgaben hinzugefügt werden können.
Zu diesem Zeitpunkt habe ich nur einen kleinen Teil dieses Thread -Pools eingeführt. ThreadPoolexecutor ist sehr skalierbar, aber die Voraussetzung, es zu erweitern, ist es, mit der Funktionsweise vertraut zu sein. Der folgende Artikel erläutert, wie die ThreadPoolexecutor -Klasse erweitert wird.
Die ava.util.concurrent.threadpoolexecutor -Klasse bietet eine umfangreiche Erweiterbarkeit. Sie können sein Verhalten anpassen, indem Sie seine Unterklasse erstellen. Zum Beispiel möchte ich eine Nachricht drucken, nachdem jede Aufgabe vorbei ist, aber ich kann das Task -Objekt nicht ändern, dann kann ich Folgendes schreiben:
ThreadPoolexecutor executor = new threadPoolexecutor (Größe, maxSize, 1, TimeUnit.Days, Warteschlange) {@Override Protected void ateExecute (runnable r, t Hrowable t) {System.out.println ("Task fertiggestellt.");
Zusätzlich zur Nachbereitungsmethode hat die ThreadPoolexecutor -Klasse auch Methoden vor der Ausführung () und beendet (), die überschrieben werden können, die vor der Ausführung der Aufgabe ausgeführt werden und nach dem gesamten Thread -Pool gestoppt werden.
Zusätzlich zum Hinzufügen von Aktionen vor und nach der Ausführung der Aufgaben können Sie auch die Ausführungsrichtlinie nach dem Hinzufügen von Aufgaben fehlschlagen, sondern auch die Ausführungsrichtlinie anpassen. Sie können die Methode SetRejectedExecutionHandler () des Thread -Pools aufrufen und die vorhandene Richtlinie durch das benutzerdefinierte AblehnungsexecutionHandler -Objekt ersetzen. ThreadPoolexecutor bietet 4 vorhandene Richtlinien, nämlich:
Threadpoolexecutor.abortpolicy: Zeigt an, dass die Aufgabe abgelehnt und eine Ausnahme ausgelöst wird
Threadpoolexecutor.discardpolicy: bedeutet, die Aufgabe abzulehnen, aber keine Aktion durchzuführen
ThreadPoolexecutor.Callerrunspolicy: Gibt an, dass die Aufgabe abgelehnt und die Aufgabe direkt im Anrufer -Thread ausgeführt wird.
Threadpoolexecutor.discardoldestpolicy: Dies bedeutet, dass die erste Aufgabe in der Task -Warteschlange zuerst verworfen wird, und dann wird die Aufgabe der Warteschlange hinzugefügt.
Hier ist ein Beispiel:
Threadpoolexecutor executor = new threadPoolexecutor (Größe, maxSize, 1, Zeiteinheit.Days, Warteschlange);
Executor.SetRejecedexecutionHandler (neuer ThreadPoolexecutor.DiscardPolicy ());
Darüber hinaus können Sie auch Ihre eigenen Richtlinien schreiben, indem Sie die AblehnungsexecutionHandler -Schnittstelle implementieren. Hier ist ein Beispiel:
Threadpoolexecutor executor = new threadpoolexecutor (3, 6, 1, Timeunit.Seconds, Queue, New RejejedExecutionHandler () {public void rejejedexecuti on (runnable r, threadpoolexecutor) {System.out.println (String.format ("Task %Deloced Desloved Deloced. . ", r.hashcode ());}});