Heim  >  Artikel  >  Java  >  Vier Möglichkeiten zur Implementierung von Multithreading in Java

Vier Möglichkeiten zur Implementierung von Multithreading in Java

WBOY
WBOYnach vorne
2022-07-04 13:56:282354Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Java, das hauptsächlich die Probleme im Zusammenhang mit den vier Möglichkeiten zur Implementierung von Multithreading löst, einschließlich der Vererbung der Thread-Klasse, der Implementierung der Callable-Schnittstelle zum Erstellen von Thread-Threads über den FutureTask-Wrapper und der Verwendung ExecutorService, Callable und Future implementieren Multithreading, das Ergebnisse usw. zurückgibt. Schauen wir sie uns gemeinsam an. Ich hoffe, dass es für alle hilfreich ist.

Vier Möglichkeiten zur Implementierung von Multithreading in Java

Empfohlenes Lernen: „Java-Video-Tutorial

JavaEs gibt vier Hauptmethoden zum Implementieren von Multithreading:

    Erben Sie die Thread-Klasse und implementieren Sie die Runnable-Schnittstelle
  • Implementieren die Aufrufbare Schnittstelle über den FutureTask-Wrapper zum Erstellen eines Thread-Threads.
  • Verwenden Sie ExecutorService, Callable Die beiden letzteren haben einen Rückgabewert.
  • 1. Vier Möglichkeiten zur Implementierung von Multithreading

  • 1. Erben Sie die Thread-Klasse, um Threads zu erstellen
  • Die Thread-Klasse ist im Wesentlichen eine Instanz, die die Runnable-Schnittstelle implementiert und eine Instanz eines Threads darstellt. Die einzige Möglichkeit, einen Thread zu starten, ist die start()-Instanzmethode der Thread-Klasse. Die start()-Methode ist eine native Methode, die einen neuen Thread startet und die run()-Methode ausführt. Es ist sehr einfach, Multithreading auf diese Weise zu implementieren, indem Sie Thread direkt durch Ihre eigene Klasse erweitern und die run()-Methode überschreiben. Sie können einen neuen Thread starten und Ihre eigene definierte run()-Methode ausführen. Beispiel:

    public class MyThread extends Thread {  
      public void run() {  
       System.out.println("MyThread.run()");  
      }  
    }  
    
    MyThread myThread1 = new MyThread();  
    MyThread myThread2 = new MyThread();  
    myThread1.start();  
    myThread2.start();
  • 2. Implementieren Sie die Runnable-Schnittstelle, um einen Thread zu erstellen.

Wenn Ihre Klasse eine andere Klasse erweitert hat, können Sie zu diesem Zeitpunkt eine Runnable-Schnittstelle wie folgt implementieren:

public class MyThread extends OtherClass implements Runnable {  
  public void run() {  
   System.out.println("MyThread.run()");  
  }  
}

In Um MyThread zu starten, müssen Sie zunächst einen Thread instanziieren und Ihre eigene MyThread-Instanz übergeben:

MyThread myThread = new MyThread();  
Thread thread = new Thread(myThread);  
thread.start();

Wenn tatsächlich ein Runnable-Zielparameter an Thread übergeben wird, ruft die run()-Methode von Thread target.run() auf, siehe zum JDK-Quellcode:

public void run() {  
  if (target != null) {  
   target.run();  
  }  
}

3. Implementieren Sie die Callable-Schnittstelle, um Thread-Threads über den FutureTask-Wrapper zu erstellen.

Die Callable-Schnittstelle (hat auch nur eine Methode) ist wie folgt definiert:

public interface Callable<V>   { 
  V call() throws Exception;   } 

public class SomeCallable<V> extends OtherClass implements Callable<V> {

    @Override
    public V call() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

}
Callable<V> oneCallable = new SomeCallable<V>();   
//由Callable<Integer>创建一个FutureTask<Integer>对象:   
FutureTask<V> oneTask = new FutureTask<V>(oneCallable);   
//注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。 
  //由FutureTask<Integer>创建一个Thread对象:   
Thread oneThread = new Thread(oneTask);   
oneThread.start();   //至此,一个线程就创建完成了。

4. und Future zum Implementieren von Threads, die Ergebnisse zurückgeben

ExecutorService. Die drei Schnittstellen Callable und Future gehören tatsächlich zum Executor-Framework. Der Thread, der das Ergebnis zurückgibt, ist eine neue Funktion, die in JDK1.5 eingeführt wurde. Mit dieser Funktion müssen Sie sich nicht mehr viel Mühe geben, um den Rückgabewert zu erhalten. Und selbst wenn Sie es selbst implementieren, kann es voller Lücken sein.

Aufgaben, die Werte zurückgeben können, müssen die Callable-Schnittstelle implementieren. Ebenso müssen Aufgaben, die keinen Wert zurückgeben, die Runnable-Schnittstelle implementieren.

Nachdem Sie die Callable-Aufgabe ausgeführt haben, können Sie einen Future-Objektaufruf für das Objekt abrufen, um das von der Callable-Aufgabe zurückgegebene Objekt abzurufen.

Hinweis: Die Get-Methode blockiert, das heißt: Der Thread gibt kein Ergebnis zurück und die Get-Methode wartet ewig.

In Kombination mit der Thread-Pool-Schnittstelle ExecutorService können Sie das legendäre Multithreading realisieren, das Ergebnisse liefert.

Im Folgenden finden Sie ein vollständiges Multithread-Testbeispiel mit den zurückgegebenen Ergebnissen. Es wurde unter JDK1.5 verifiziert und kann problemlos direkt verwendet werden. Der Code lautet wie folgt:

import java.util.concurrent.*;  
import java.util.Date;  
import java.util.List;  
import java.util.ArrayList;  

/** 
* 有返回值的线程 
*/  
@SuppressWarnings("unchecked")  
public class Test {  
public static void main(String[] args) throws ExecutionException,  
    InterruptedException {  
   System.out.println("----程序开始运行----");  
   Date date1 = new Date();  

   int taskSize = 5;  
   // 创建一个线程池  
   ExecutorService pool = Executors.newFixedThreadPool(taskSize);  
   // 创建多个有返回值的任务  
   List<Future> list = new ArrayList<Future>();  
   for (int i = 0; i < taskSize; i++) {  
    Callable c = new MyCallable(i + " ");  
    // 执行任务并获取Future对象  
    Future f = pool.submit(c);  
    // System.out.println(">>>" + f.get().toString());  
    list.add(f);  
   }  
   // 关闭线程池  
   pool.shutdown();  

   // 获取所有并发任务的运行结果  
   for (Future f : list) {  
    // 从Future对象上获取任务的返回值,并输出到控制台  
    System.out.println(">>>" + f.get().toString());  
   }  

   Date date2 = new Date();  
   System.out.println("----程序结束运行----,程序运行时间【"  
     + (date2.getTime() - date1.getTime()) + "毫秒】");  
}  
}  

class MyCallable implements Callable<Object> {  
private String taskNum;  

MyCallable(String taskNum) {  
   this.taskNum = taskNum;  
}  

public Object call() throws Exception {  
   System.out.println(">>>" + taskNum + "任务启动");  
   Date dateTmp1 = new Date();  
   Thread.sleep(1000);  
   Date dateTmp2 = new Date();  
   long time = dateTmp2.getTime() - dateTmp1.getTime();  
   System.out.println(">>>" + taskNum + "任务终止");  
   return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";  
}  
}

2. Multithreading-bezogenes Wissen

1 Was ist der Unterschied zwischen Runnable und Callable?

·

Der Hauptunterschied besteht darin, dass die Run-Methode der Runnable-Schnittstelle keinen Rückgabewert hat.


·

Die Call-Methode der Callable-Schnittstelle hat einen Rückgabewert und unterstützt die generische Runnable-Schnittstelle löst nur Laufzeitausnahmen aus und kann diese nicht abfangen und verarbeiten.

·

Aufrufbare Schnittstellenaufrufmethode ermöglicht das Auslösen von Ausnahmen und das Abrufen von Ausnahmeinformationen

2. Wie startet man einen neuen Thread und was ist der Unterschied zwischen dem Aufruf der Start- und Ausführungsmethoden? ?

·

Das Thread-Objekt ruft die Ausführungsmethode auf, ohne den Thread zu starten. Nur Objekte rufen Methoden auf.

·
Die Thread-Objektaufrufe beginnen, den Thread zu öffnen, und ermöglichen es der JVM, die Ausführungsmethode im geöffneten Thread aufzurufen. Durch Aufrufen der Startmethode kann der Thread gestartet und in den Bereitschaftszustand versetzt werden ist nur eine übliche Thread-Methode oder wird im Hauptthread ausgeführt.

3. Grundlegende Thread-bezogene Methoden?

Zu den grundlegenden Methoden im Zusammenhang mit Threads gehören Wait, Notify, NotifyAll, Sleep, Join, Yield usw.

· Thread-Warten (Wait) Der Thread, der diese Methode aufruft, wechselt in den Wartezustand und wartet nur auf Benachrichtigungen von Ein anderer Thread wird unterbrochen oder es wird darauf hingewiesen, dass nach dem Aufruf der Methode wait() die Sperre des Objekts aufgehoben wird. Daher wird die Wartemethode im Allgemeinen in synchronisierten Methoden oder synchronisierten Codeblöcken verwendet.

·

Thread-Sleep (Schlaf) Sleep führt dazu, dass der aktuelle Thread in den Ruhezustand versetzt wird Die Methode wait() führt dazu, dass der aktuelle Thread in den WATING-Status wechselt.

· Thread yield (yield) yield führt dazu, dass der aktuelle Thread die CPU-Ausführungszeitscheibe zurückgibt und erneut mit anderen Threads um die CPU-Zeitscheibe konkurriert. Im Allgemeinen haben Threads mit hoher Priorität eine größere Chance, erfolgreich um CPU-Zeitscheiben zu konkurrieren, dies gilt jedoch nicht unbedingt. Einige Betriebssysteme reagieren nicht empfindlich auf Thread-Priorität.

· Thread-Unterbrechung (Interrupt) Die ursprüngliche Absicht der Unterbrechung eines Threads besteht darin, dem Thread ein Benachrichtigungssignal zu geben, das sich auf ein Interrupt-Flag innerhalb des Threads auswirkt. Aus diesem Grund ändert der Thread selbst seinen Status (z. B. Blockierung, Beendigung usw.) nicht ()-Methode eines Threads im aktuellen Thread wechselt in den Blockierungszustand und kehrt zum Beenden des aktuellen Threads vom Blockierungszustand in den Bereitschaftszustand zurück

· Thread-Wake-up (Notify)-Methode notify() in der Object-Klasse. Weckt einen einzelnen Thread auf, der auf dem Monitor dieses Objekts wartet. Wenn alle Threads auf dieses Objekt warten, wird einer der Threads zum Aufwecken ausgewählt Die Auswahl ist willkürlich und erfolgt, wenn eine Entscheidung über die Implementierung getroffen wird. Die Methode wait() wartet auf dem Monitor des Objekts, bis der aktuelle Thread die Sperre für dieses Objekt aufgibt, bevor der Thread aktiviert wird Der aufgeweckte Thread kann weiterhin auf normale Weise mit allen anderen aktiv synchronisierten Threads ausgeführt werden. Eine ähnliche Methode ist notifyAll(), die alle auf dem Monitor wartenden Threads wieder aufweckt.

5. Was ist der Unterschied zwischen wait() und sleep()?

·

① Von verschiedenen Klassen wait(): von der Object-Klasse; sleep(): von der Thread-Klasse;

· ② Bezüglich der Freigabe der Sperre: wait(): Die Sperre wird freigegeben während des Wartevorgangs; Sleep(): Die Sperre wird während des Wartevorgangs nicht aufgehoben

· ③ Anwendungsbereich: Wait(): muss in synchronisierten Codeblöcken verwendet werden;

· ④ Müssen Sie Ausnahmen abfangen?

Multi-Threading erfolgt gleichzeitig

. Eine CPU kann zu einem bestimmten Zeitpunkt nur ein Programm ausführen, das heißt, sie kann nur einen Prozess gleichzeitig ausführen. Die CPU wechselt ständig zwischen diesen Prozessen und jeder Thread wird einmal ausgeführt. Da die Ausführungsgeschwindigkeit der CPU im Verhältnis zu unserer Wahrnehmung zu hoch ist, haben wir zwar das Gefühl, dass mehrere Prozesse gleichzeitig ausgeführt werden, obwohl die CPU die Ausführung zwischen mehreren Prozessen wechselt.

Die CPU wechselt zwischen mehreren Prozessen. Wenn wir zu viele Programme öffnen, wird auch die Zeit, die die CPU benötigt, um zu jedem Prozess zu wechseln, länger und wir werden auch das Gefühl haben, dass die Maschine langsamer läuft. Daher kann die sinnvolle Verwendung von Multithreading die Effizienz verbessern, eine umfassende Verwendung führt jedoch nicht zu einer Verbesserung der Effizienz.

Die Multithreading-Technologie löst hauptsächlich das Problem der Ausführung mehrerer Threads in der Prozessoreinheit. Sie kann die Leerlaufzeit der Prozessoreinheit erheblich reduzieren und die Durchsatzkapazität der Prozessoreinheit erhöhen.

Empfohlenes Lernen: „

Java-Video-Tutorial

Das obige ist der detaillierte Inhalt vonVier Möglichkeiten zur Implementierung von Multithreading in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen