Heim  >  Artikel  >  Java  >  Parallele Java-Programmierung: Wie verwende ich die Thread-Klasse?

Parallele Java-Programmierung: Wie verwende ich die Thread-Klasse?

零下一度
零下一度Original
2017-06-23 09:16:041987Durchsuche
Gleichzeitige Java-Programmierung: Verwendung der Thread-Klasse
 
Das Folgende ist die Inhaltsübersicht dieses Artikels:
1. Der Status des Threads
2. Kontextwechsel
3. Methoden in der Thread-Klasse
 
Nachdruck von:
 

1. Thread-Status

 Ein Thread durchläuft von der Erstellung bis zum endgültigen Tod mehrere Zustände. Im Allgemeinen umfassen Threads die folgenden Zustände: Erstellung (neu), bereit (ausführbar), ausgeführt (läuft), blockiert (blockiert), Wartezeit, Warten und Tod (tot).
 
Das Bild unten beschreibt den Zustand eines Fadens von der Schöpfung bis zum Tod:

In einigen Tutorials werden „Blockiert“, „Warten“ und „Zeitwarten“ zusammenfassend als Blockierungszustände bezeichnet. Dies ist auch möglich, aber hier möchte ich den Zustand des Threads mit dem Methodenaufruf in Java verknüpfen, also kombiniere ich die beiden Zustände des Wartens und Zeit des Wartens getrennt.

2. Kontextwechsel

 Bei einer Single-Core-CPU (bei einer Multi-Core-CPU wird darunter ein Kern verstanden) kann die CPU jeweils nur einen Thread ausführen Der Wechsel zur Ausführung eines anderen Threads während der Ausführung eines Threads wird als Thread-Kontextwechsel bezeichnet (dasselbe gilt für Prozesse).
 

3. Methoden in der Thread-Klasse

Wenn wir uns den Quellcode der java.lang.Thread-Klasse ansehen, können wir Folgendes sehen:

Die Thread-Klasse implementiert die Runnable-Schnittstelle. In der Thread-Klasse gibt es beispielsweise einige Schlüsselattribute Durch die Parameter im Konstruktor der Thread-Klasse angegeben, gibt die Priorität die Priorität des Threads an (der Maximalwert ist 10, der Minimalwert ist 1, der Standardwert ist 5), der Daemon gibt an, ob der Thread ein Daemon ist Thread und Ziel gibt die auszuführende Aufgabe an.
 Die folgenden Methoden werden häufig in der Thread-Klasse verwendet:
Die folgenden Methoden beziehen sich auf den Laufstatus des Threads:
1 ) Startmethode
Start() wird zum Starten eines Threads verwendet. Wenn die Startmethode aufgerufen wird, startet das System einen neuen Thread, um benutzerdefinierte Unteraufgaben auszuführen zum entsprechenden Thread.
2) run-Methode
Die run()-Methode muss nicht vom Benutzer aufgerufen werden. Wenn ein Thread über die Startmethode gestartet wird, erhält der Thread CPU-Ausführungszeit gibt den Hauptteil der Ausführungsmethode ein, um bestimmte Aufgaben auszuführen. Beachten Sie, dass Sie beim Erben der Thread-Klasse die Ausführungsmethode überschreiben und die spezifischen Aufgaben definieren müssen, die in der Ausführungsmethode ausgeführt werden sollen.
 3) Schlafmethode
Es gibt zwei überladene Versionen der Schlafmethode:
Ruhezustand ist gleichbedeutend damit, den Thread schlafen zu lassen, die CPU zu übergeben und die CPU andere Aufgaben ausführen zu lassen.
Beachten Sie jedoch, dass die Schlafmethode die Sperre nicht aufhebt. Das heißt, wenn der aktuelle Thread eine Sperre für ein Objekt hält, können andere Threads nicht auf das Objekt zugreifen, selbst wenn Die Schlafmethode wird aufgerufen. Es wird deutlich, wenn Sie sich das folgende Beispiel ansehen:
1
2
3
sleep(long millis)     //参数为毫秒
 
sleep(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒
123
sleep(long millis) //Der Parameter ist Millisekunden sleep(long millis,int nanoseconds) //Der erste Parameter ist Millisekunden, der zweite Parameter ist Nanosekunden
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Test {
     
    private int i = 10;
    private Object object = new Object();
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        MyThread thread2 = test.new MyThread();
        thread1.start();
        thread2.start();
    } 
     
     
    class MyThread extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                    System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                    Thread.currentThread().sleep(10000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
}
123456789101112131415 16 1718192021222324252627282930313233
öffentlicher Klassentest {  private int i = 10; private Object object = new Object(); public static void main(String[] args) throws IOException { Test test = new Test(); MyThread thread1 = test.new MyThread(); MyThread thread2 = test.new MyThread(); thread1.start( ); thread2.start(); } @Override public void run() { synchronisiert (object) { i++; System.out .println("i:"+ i); try { System. out.println("Thread"+Thread.currentThread().getName()+"Enter Sleep"); Thread.currentThread().sleep(10000); } Catch ( InterruptedException e) { }            System .out.println("Thread"+Thread.currentThread().getName()+"Sleep End"); i++ ; System.out.println("i:"+ i); } } }}
Ausgabeergebnisse:
Bestimmte Aufgaben wurden nicht ausgeführt. Erst wenn Thread-0 die Ausführung abschließt und Thread-0 die Objektsperre aufhebt, beginnt Thread-1 mit der Ausführung.

Beachten Sie, dass beim Aufruf der Sleep-Methode die InterruptedException abgefangen oder an die obere Ebene geworfen werden muss. Wenn die Thread-Ruhezeit abgelaufen ist, wird sie möglicherweise nicht sofort ausgeführt, da die CPU zu diesem Zeitpunkt möglicherweise andere Aufgaben ausführt. Der Aufruf der Sleep-Methode entspricht also dem Versetzen des Threads in einen blockierenden Zustand.

 4) Yield-Methode
Der Aufruf der Yield-Methode führt dazu, dass der aktuelle Thread CPU-Berechtigungen übergibt und die CPU andere Threads ausführen lässt. Es ähnelt der Schlafmethode und hebt die Sperre ebenfalls nicht auf. Yield kann jedoch nicht die spezifische Zeit für die Übergabe der CPU steuern. Darüber hinaus kann die Yield-Methode nur Threads mit derselben Priorität die Möglichkeit geben, CPU-Ausführungszeit zu erhalten.
Beachten Sie, dass der Aufruf der Yield-Methode den Thread nicht in den Blockierungszustand versetzt, sondern ihn in den Bereitschaftszustand zurückversetzt. Es muss nur darauf gewartet werden, dass die CPU-Ausführungszeit wiederhergestellt wird, was sich von der unterscheidet Schlafmethode.
5) Join-Methode
Die Join-Methode hat drei überladene Versionen:
1
2
3
1
2
3
join()
join(long millis)     //参数为毫秒
join(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒
join()join(long millis) //Der Parameter ist Millisekundenjoin(long millis,int nanoseconds) //Der erste Parameter ist Millisekunden, der zweite Parameter ist Nanosekunden
Wenn die Methode thread.join im Hauptthread aufgerufen wird, wartet die Hauptmethode darauf, dass der Thread-Thread die Ausführung abschließt, oder wartet eine bestimmte Zeit. Wenn die Join-Methode ohne Parameter aufgerufen wird, warten Sie, bis der Thread die Ausführung abgeschlossen hat. Wenn die Join-Methode mit einem angegebenen Zeitparameter aufgerufen wird, warten Sie auf ein bestimmtes Ereignis.
Sehen Sie sich das folgende Beispiel an:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Test {
     
    public static void main(String[] args) throws IOException  {
        System.out.println("进入线程"+Thread.currentThread().getName());
        Test test = new Test();
        MyThread thread1 = test.new MyThread();
        thread1.start();
        try {
            System.out.println("线程"+Thread.currentThread().getName()+"等待");
            thread1.join();
            System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("进入线程"+Thread.currentThread().getName());
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                // TODO: handle exception
            }
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
        }
    }
}
12345678 9101112131415 1617181920212223242526272829 30
public class Test {  public static void main(String[] args) throws IOException { System .out.println("Enter thread"+Thread.currentThread().getName()); Test test = new Test(); MyThread thread1 = test.new MyThread( ) ; thread1.start(); try { System.out.println("Thread"+Thread.currentThread().getName()+"Wait " );    thread1.join();     System.out.println("Thread"+Thread.currentThread().getName()+"Ausführung fortsetzen"); 🎜>         } Catch (InterruptedException e) {                                                                                                                                                              🎜> } > enter Thread"+Thread.currentThread().getName()); try { Thread. currentThread().sleep(5000); } Catch (InterruptedException e ) {                                                                                                                                                 Ausnahme behandeln ");. } }}
Ausgabeergebnis:

Es ist ersichtlich, dass der Haupt-Thread aufgerufen wird, wenn die Methode thread1.join() aufgerufen wird Wechseln Sie in den Wartezustand und warten Sie, bis die Ausführung von Thread1 abgeschlossen ist, bevor Sie fortfahren.
Tatsächlich ruft der Aufruf der Join-Methode die Wartemethode von Object auf. Dies kann durch Anzeigen des Quellcodes festgestellt werden:
 

wait Methode Dies führt dazu, dass der Thread in einen blockierten Zustand wechselt, die vom Thread gehaltene Sperre aufhebt und CPU-Ausführungsberechtigungen übergibt.
Da die Wartemethode den Thread dazu veranlasst, die Objektsperre aufzuheben, bewirkt die Join-Methode auch, dass der Thread die für ein Objekt gehaltene Sperre aufhebt. Die spezifische Verwendung der Wartemethode wird im folgenden Artikel beschrieben.
6) Interrupt-Methode
Interrupt bedeutet, wie der Name schon sagt, Unterbrechung. Der alleinige Aufruf der Interrupt-Methode kann dazu führen, dass der Thread im blockierten Zustand eine Ausnahme auslöst, d laufender Thread.
Hier ist ein Beispiel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                System.out.println("进入睡眠状态");
                Thread.currentThread().sleep(10000);
                System.out.println("睡眠完毕");
            } catch (InterruptedException e) {
                System.out.println("得到中断异常");
            }
            System.out.println("run方法执行完毕");
        }
    }
}
12345678 910111213141516171819202122232425262728
öffentlicher Klassentest {                                                                                                                                                       thread = test.new MyThread(); thread.start(); try { Thread.currentThread() .sleep(2000);                                                                                                                             🎜> Versuchen Sie es mit {System.out.println("Enter Sleep state");Thread.currentThread().sleep(10000);System.out. println("Schlaf abgeschlossen"); (InterruptedException e) {                                                                                                                          use using ‐ using System.out.println's("Erhalten einer Interrupt-Ausnahme" 🎜> } } }
Ausgabeergebnis:

Wie hier zu sehen ist, kann der unterbrochene Thread durch die Interrupt-Methode unterbrochen werden. Kann ein Thread in einem nicht blockierenden Zustand unterbrochen werden? Schauen Sie sich das folgende Beispiel an:
tbody>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(i
                System.out.println(i+" while循环");
                i++;
            }
        }
    }
}
12 345678910111213141516 17181920212223 2425
öffentlicher Klassentest {                                                IOException-Test test = neuer Test(); MyThread thread = test.new MyThread(); thread.start(); try {                                                                         🎜>        thread.interrupt (); ) { int i = 0; While (I & LT; Integer.max_value) { System.out.println (I+"While Cycle" ); 🎜> i++;
Wenn Sie dieses Programm ausführen, werden Sie feststellen, dass die while-Schleife so lange ausgeführt wird, bis der Wert der Variablen i Integer.MAX_VALUE überschreitet. Daher kann der direkte Aufruf der Interrupt-Methode den laufenden Thread nicht unterbrechen.
Wenn der laufende Thread jedoch mit isInterrupted () unterbrochen werden kann, da der Aufruf der Interrupt-Methode dem Setzen des Interrupt-Flags auf true entspricht, können Sie den Thread durch Aufruf von isInterrupted () unterbrechen, um festzustellen, ob der Interrupt erfolgt Flag ist gesetzt. Zum Beispiel der folgende Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Test {
     
    public static void main(String[] args) throws IOException  {
        Test test = new Test();
        MyThread thread = test.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(!isInterrupted() && i
                System.out.println(i+" while循环");
                i++;
            }
        }
    }
}
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyThread extends Thread{
        private volatile boolean isStop = false;
        @Override
        public void run() {
            int i = 0;
            while(!isStop){
                i++;
            }
        }
         
        public void setStop(boolean stop){
            this.isStop = stop;
        }
    }
56789 1011121314151617181920212223 2425
öffentlicher Klassentest                         wirft IOException {          Test test = neuer Test( );             MyThread thread = test.new MyThread(); > try { Thread.currentThread().sleep(2000); } Catch (InterruptedException e) {       }        thread.interrupt();                                                    public void run( ) { int i = 0; while(!isInterrupted() && i
Wenn Sie es ausführen, werden Sie feststellen, dass nach dem Drucken mehrerer Werte , stoppt die while-Schleife den Druckvorgang. Es wird jedoch im Allgemeinen nicht empfohlen, den Thread auf diese Weise zu unterbrechen. Im Allgemeinen wird der MyThread-Klasse ein Attribut isStop hinzugefügt, um zu markieren, ob die while-Schleife beendet werden soll, und dann wird der Wert von isStop bestimmt die while-Schleife.
12 345678910 11121314 Klasse MyThread erweitert Thread{        private volatile boolean isStop = false; while(!isStop ){ i++; } } public void set Stop(boolean stop ){ this.isStop = stop; } }
Anschließend können Sie die while-Schleife beenden, indem Sie die setStop-Methode außerhalb aufrufen.
7) Stop-Methode
Die Stop-Methode ist eine aufgegebene Methode und eine unsichere Methode. Da der Aufruf der Stop-Methode den Aufruf der Run-Methode direkt beendet und einen ThreadDeath-Fehler auslöst. Wenn der Thread eine Objektsperre hält, wird die Sperre vollständig aufgehoben, was zu einem inkonsistenten Objektstatus führt. Daher wird die Stoppmethode grundsätzlich nicht verwendet.
8) Zerstörungsmethode
Die Zerstörungsmethode ist ebenfalls eine aufgegebene Methode. Wird grundsätzlich nicht verwendet.
Im Folgenden sind mehrere Methoden im Zusammenhang mit Thread-Attributen aufgeführt:
1) getId
Wird verwendet, um die Thread-ID abzurufen
2) getName und setName
Wird verwendet, um den Thread-Namen abzurufen oder festzulegen.
 3) getPriority und setPriority
  werden verwendet, um die Thread-Priorität abzurufen und festzulegen.
 4) setDaemon und isDaemon
  werden verwendet, um festzulegen, ob der Thread ein Daemon-Thread wird, und um zu bestimmen, ob der Thread ein Daemon-Thread ist.
Der Unterschied zwischen Daemon-Threads und Benutzer-Threads besteht darin, dass der Daemon-Thread von dem Thread abhängt, der ihn erstellt hat, während dies beim Benutzer-Thread nicht der Fall ist. Um ein einfaches Beispiel zu nennen: Wenn im Hauptthread ein Daemon-Thread erstellt wird und die Ausführung der Hauptmethode beendet ist, stirbt auch der Daemon-Thread. Der Benutzerthread wird nicht weiter ausgeführt, bis er abgeschlossen ist. In der JVM ist ein Garbage-Collector-Thread ein Daemon-Thread.
Die Thread-Klasse verfügt über eine häufig verwendete statische Methode currentThread(), um den aktuellen Thread abzurufen.
Die meisten Methoden in der Thread-Klasse wurden oben erwähnt. Wie bewirken die Methodenaufrufe in der Thread-Klasse also Änderungen im Thread-Status? Das folgende Bild ist eine Verbesserung zum obigen Bild:

Das obige ist der detaillierte Inhalt vonParallele Java-Programmierung: Wie verwende ich die Thread-Klasse?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Vier Möglichkeiten zum Parsen von XMLNächster Artikel:Vier Möglichkeiten zum Parsen von XML

In Verbindung stehende Artikel

Mehr sehen