Multithreading ist ein sehr wichtiger Wissenspunkt in Java. Hier fasst der Herausgeber Java Thread Multithreading zu Ihnen zusammen, was sehr nützlich ist. Ich hoffe du kannst es beherrschen.
1. Der Lebenszyklus eines Fadens und der fünf Grundzustände
In Bezug auf den Lebenszyklus von Fäden in Java schauen wir uns zunächst das folgende klassische Bild an:
Die obige Abbildung deckt im Grunde die wichtigen Wissenspunkte des Multi-Threading in Java ab. Sobald Sie die Wissenspunkte in der obigen Abbildung beherrschen, beherrschen Sie das Multi-Threading in Java im Grunde genommen. Hauptsächlich einschließlich:
Java -Threads haben fünf Grundzustände
Neuer Zustand (neu): Wenn ein Thread -Objektpaar erstellt wird, tritt ein neuer Zustand ein, wie z. B. Thread t = new myThread ();
Ready State (Runnable): Wenn die Start () -Methode des Thread -Objekts (t.Start ();), tritt der Thread in den Bereitschaftszustand ein. Ein Thread im rede Zustand bedeutet nur, dass der Thread fertig ist und darauf wartet, dass die CPU die Ausführung jederzeit plant, und nicht, dass der Thread unmittelbar nach T.Start () ausgeführt wird.
Auslaufstatus: Wenn die CPU beginnt, Threads im vorbereitenden Zustand zu planen, kann der Thread wirklich ausgeführt werden, dh in den laufenden Status. Hinweis: Der Ready -Status ist der einzige Eintrag in den laufenden Status, dh wenn ein Thread in den ausführenden Zustand eingeben möchte, muss er zunächst im vorbereitenden Zustand sein.
Blockierter Zustand: Aus irgendeinem Grund gibt ein Thread im laufenden Status die Verwendung der CPU vorübergehend auf und stoppt die Ausführung. Zu diesem Zeitpunkt tritt es in den Blockierstaat ein. Es wird nicht die Chance haben, von der CPU erneut aufgerufen zu werden, um in den laufenden Zustand einzugeben.
Nach den Gründen des Blockierens können Blockierungszustände in drei Typen unterteilt werden:
1. Warten auf die Blockierung: Der Thread im laufenden Status führt die Wait () -Methode aus, damit der Thread das Warten auf den Blockierstatus eingeht.
2. Synchronisierte Blockierung- Der Thread erfasst das synchronisierte Synchronisationsschloss (weil das Schloss von anderen Fäden besetzt ist) und tritt in den synchronisierten Blockierungszustand ein.
3. Andere Blockierung-Der Thread tritt in einen Blockierungsstatus ein, indem er Schlaf () oder Join () des Threads anruft oder eine E/A-Anfrage ausstellt. Wenn der Sleep () -State zeitlich abgestimmt war, Join () darauf wartete, dass der Faden endet oder zeitlich abgestimmt hat oder die E/A-Verarbeitung abgeschlossen wurde, wurde der Thread wieder in den bereiten Zustand eingegeben.
TOT: Der Thread hat die Ausführung der Ausnahme ausgesetzt oder verlässt die Run () -Methode aufgrund einer Ausnahme, und der Thread beendet seinen Lebenszyklus.
2. Schöpfung und Start von Java Multithreads
In Java gibt es drei grundlegende Formen der Thread -Erstellung
1. Erben Sie die Thread -Klasse und überschreiben Sie die Run () -Methode der Klasse.
class MyThread extends Thread {private int i = ;@Overridepublic void run() {for (i = ; i < ; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}} public class ThreadTest {public static void main(String[] args) {for (int i = ; i < ; i++) {System.out.println (Thread.currentThread (). GetName () + "" + i); if (i ==) {Thread myThread = new myThread (); // Erstellen Sie einen neuen Thread mythead Dieser Thread tritt in den neuen Status -Thread mythead = new MyThread () ein; // Erstellen Sie einen neuen Thread mythread Dieser Thread tritt in den neuen Zustand mythead.start () ein; // rufen Sie die Start () -Methode an, damit der Thread den Ready State MyThread.Start () eingibt. // Rufen Sie die Methode start () auf, um den Thread den Ready -Status einzugeben}}}} eingeben Wie oben gezeigt, erben Sie die Thread -Klasse und überschreiben Sie die Run () -Methode, eine neue MyThread -Klasse von Threads wird definiert, wobei die Methode der Methode der Run () -Methode die Aufgabe darstellt, die der Thread ausführen muss, und als Thread Execution -Körper bezeichnet wird. Beim Erstellen dieses Thread -Klassenobjekts wird ein neuer Thread erstellt und tritt in den neuen Thread -Status ein. Wenn Sie die vom Thread -Objekt verwiesene Start () -Methode aufrufen, tritt der Thread in den Bereitschaftszustand ein. Zu diesem Zeitpunkt kann der Thread je nach Timing der CPU nicht sofort ausgeführt werden.
2. Implementieren Sie die Runnable -Schnittstelle und überschreiben Sie die Run () -Methode der Schnittstelle. Die Run () -Methode ist auch ein Thread -Ausführungsgremium, erstellen Sie eine Instanz der Runnable -Implementierungsklasse und verwenden diese Instanz als Ziel der Thread -Klasse, um ein Thread -Objekt zu erstellen. Das Thread -Objekt ist das reale Thread -Objekt.
Klasse Myrunnable Implements Runnable {private int i =; @Overridepublic void run () {für (i =; i <; i ++) {System.out.println (Thread.Current thread (). getName ()+"+i);}}} öffentliche Klasse threadte {öffentliches statisches statisches statisches statisches statisches statisches statisches statisches statisches itaid (string [] args) {auf (intest {public {public static void itac) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) (String) ()ömerische {System.out.println (Thread.currentThread (). GetName () + "" + i); if (i ==) {runnable myrunnable = new Myrunnable (); // Erstellen Sie ein Objekt von Runnable -Implementierungsklassen -Thread = neuer Thread (Myrunnable); // Verwenden Sie Myrunnable als Thread -Ziel, um einen neuen Thread -Thread = neuer Thread (Myrunnable) zu erstellen. // Rufen Sie die Methode start () auf, um den Thread den thread ready -Status einzugeben. Start ();}}}} Ich glaube, dass jeder mit den oben genannten zwei Möglichkeiten vertraut ist, neue Threads zu erstellen. Wie ist die Beziehung zwischen Thread und Runnable? Schauen wir uns zunächst das folgende Beispiel an.
public class threadtest {public static void main (String [] args) {für (int i =; i <; i ++) {System.out.println (thread.currentThread (). MyThread (Myrunnable); Thread.Start ();}}}} Klasse Myrunnable Implements Runnable {private int i =; @Overridepublic void Run () {System.out.println ("in Myrunnable Run"); für (i =; i <; i+ *) {system.println (thread.). " + i);}}}class MyThread extends Thread {private int i = ;public MyThread(Runnable runnable){super(runnable);}@Overridepublic void run() {System.out.println("in MyThread run");for (i = ; i < ; i++) {System.out.println(Thread.currentThread().getName() + "" + i);}}} In ähnlicher Weise gilt dies auch für das Erstellen von Threads, die die Runnable -Schnittstelle implementieren. Der Unterschied besteht darin
Thread Thread = New MyThread (Myrunnable);
Kann diese Methode also erfolgreich einen neuen Thread erstellen? Die Antwort lautet ja. Was den Thread -Ausführungskörper zu diesem Zeitpunkt betrifft, so ist die Run () -Methode in der Myrunnable -Schnittstelle oder in der Run () -Methode in der MyThread -Klasse? Durch die Ausgabe wissen wir, dass der Thread -Ausführungskörper die Run () -Methode in der MyThread -Klasse ist. Tatsächlich ist der Grund sehr einfach, da die Thread -Klasse selbst auch die Runnable -Schnittstelle implementiert und die Run () -Methode zuerst in der Runnable -Schnittstelle definiert ist.
öffentliche Schnittstelle Runnable {public abstract void run ();} Schauen wir uns die Implementierung der Run () -Methode in der Runnable -Schnittstelle in der Thread -Klasse an:
@Overridepublic void run () {if (target! = Null) {target.run ();}} Das heißt, bei der Ausführung der Run () -Methode in der Thread -Klasse wird die Run () -Methode im Ziel zuerst bestimmt. Wenn es vorhanden ist, wird die Run () -Methode im Ziel ausgeführt, dh die Run () -Methode in der Klasse, die die Runnable -Schnittstelle implementiert und die Run () -Methode überschreibt. In den oben angegebenen Spalten wird jedoch aufgrund der Existenz des Polymorphismus die Run () -Methode in der Thread -Klasse überhaupt nicht ausgeführt, sondern der Laufzeittyp, dh die Run () -Methode in der MyThread -Klasse, wird direkt ausgeführt.
3. Erstellen Sie Threads mit Callable und zukünftigen Schnittstellen. Insbesondere erstellt es eine Implementierungsklasse für die Callable -Schnittstelle und implementiert die Clall () -Methode. Verwenden Sie die Futuretask -Klasse, um das Objekt für Callable -Implementierungsklassen einzuwickeln und dieses Futuretask -Objekt als Ziel des Thread -Objekts, um einen Thread zu erstellen.
Es scheint ein bisschen kompliziert, aber es wird klar sein, wenn Sie sich ein Beispiel direkt ansehen.
public class threadTest {public static void main (String [] args) {Callable <Integer> mycallable = new MyCallable (); // MyCallable -Objekt -Futuretask <Ganzzahl> ft = New Futuretask <Ganzzahl> (myCallable); // Futuretask verwenden, um mycallable Objekt für (int i =; i <; i ++) {System.out.println (Thread.currentThread (). if (i ==) {Thread thread = neuer Thread (ft); // Futuretask -Objekt erstellt einen neuen Thread als Ziel des Thread -Objekt -Threads.start (); // Thread tritt in den Ready State}} System.out.println ("Haupt Thread für die Ausführung der Schleife ab ..."); try {int sum = ft.get (); // das Ergebnis erhalten, das von der CALL () -Methode im neu erstellten neuen Thread -System zurückgegeben wird. Methode, die CALL () -Methode hat den Rückgabewert @Overridepublic Integer call () {int sum =; für (; i <; i ++) {System.out.println (Thread.currentThread (). getName () +" +i); Zunächst stellten wir fest, dass bei der Implementierung der Callable -Schnittstelle die Run () -Methode nicht mehr die Run () -Methode, sondern die Call () -Methode ist. Diese CALL () -Methode ist die Thread -Ausführungskörper und hat auch einen Rückgabewert! Beim Erstellen eines neuen Threads wird das mykallierbare Objekt über Futuretask eingewickelt und auch als Ziel für das Thread -Objekt verwendet. Schauen Sie sich dann die Definition der Futuretask -Klasse an:
öffentliche Klasse Futuretask <V> Implementiert RunnableFuture <V> {// ....} öffentliche Schnittstelle RunnableFuture <V> erweitert Runnable, Future <V> {void run ();} Daher stellten wir fest, dass die Futuretask -Klasse sowohl runnable als auch künftige Schnittstellen tatsächlich implementiert, was sie über die doppelten Eigenschaften der Zukunft und der Runnable verfügt. Durch die Runnable -Funktion kann es als Ziel des Thread -Objekts verwendet werden, und die zukünftige Funktion ermöglicht es ihm, den Rückgabewert der Call () -Methode im neu erstellten Thread zu erhalten.
Nachdem wir dieses Programm ausgeführt haben, stellen wir fest, dass Sum = 4950 immer die letzte Ausgabe ist. "Der Hauptfaden für die Schleife wurde ausgeführt ..." wird wahrscheinlich in der Mitte der Kinderfadenschleife ausgegeben. Aus dem Thread -Planungsmechanismus der CPU wissen wir, dass es kein Problem mit dem Ausgangszeitpunkt "Der Haupt -Thread für die Schleife wurde ausgeführt wurde ...". Warum wird Summe = 4950 für immer ausgegeben?
Der Grund dafür ist, dass wenn die Methode des untergeordneten Threads CALL () über die Methode ft.get () erhalten wird, wenn die Methode des untergeordneten Threads noch nicht ausgeführt wurde, blockiert die Methode ft.get (), bis die Methode call () ausgeführt wird, bevor der Rückgabewert erhalten werden kann.
Die obigen erklärt hauptsächlich drei gängige Methoden der Fadenerstellung. Für das Start von Threads werden sie alle als start () -Methode des Thread -Objekts bezeichnet. Es ist wichtig zu beachten, dass die Start () -Methode nicht zweimal auf demselben Thread -Objekt aufgerufen werden kann.
III. Bereit, Run- und Todstatus von Java Multithreading
Der Ready -Status wird in den laufenden Status umgewandelt: Wenn dieser Thread die Prozessorressource erhält;
Der laufende Status wird in den Ready -Status umgewandelt: Wenn dieser Thread die Rendite () -Methode aktiv aufruft oder die Prozessorressourcen während des Laufens verliert.
Der laufende Zustand wird in den toten Zustand umgewandelt: Wenn die Thread -Ausführungsbehörde abgeschlossen ist oder eine Ausnahme auftritt.
Es sollte hier angemerkt werden, dass, wenn die Rendite () -Methode des Threads aufgerufen wird, der Thread vom Laufstatus in den readitionellen Zustand wechselt, aber welcher Thread im Bereitschaftszustand in der CPU geplant ist, hat eine gewisse Zufälligkeit. Daher kann es geschehen, dass die CPU nach dem A -Thread die Rendite () -Methode aufruft, die CPU den A Thread noch plant.
Aufgrund der tatsächlichen geschäftlichen Anforderungen wird häufig aufgetaucht, dass ein Thread mit einer bestimmten Gelegenheit beendet werden muss, damit er in einen toten Zustand eintritt. Die derzeit häufigste Methode besteht darin, eine boolesche Variable festzulegen, und wenn die Bedingungen erfüllt sind, wird die Thread -Ausführungsbehörde schnell ausgeführt. wie:
public class threadtest {public static void main (String [] args) {Myrunnable Myrunnable = new Myrunnable (); Thread = neuer Thread (Myrunnable); für (int i =; i <; {thread.start ();} if (i ==) {Myrunnable.StOpthead ();}}}} Klasse Myrunnable Implements Runnable {private boolean stop; @Overridepublic void Run () {for (int i =; i <&&!). " + i);}} public void stopthread () {this.stop = true;}}Das obige ist eine umfassende Analyse des Java-Thread-Multi-Threading, das der Editor Ihnen vorgestellt hat. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird Ihnen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!