Sie müssen Threads verarbeiten, um eine asynchrone und parallele Verarbeitung in Java durchzuführen. Dieser Artikel wurde mit der Hoffnung geschrieben, dass Anfänger bis Fortgeschrittene in Java eine grobe Vorstellung von Threads bekommen.
Threads sind wie der Pfad, den Sie beim Ausführen eines Programms einschlagen. Zum Beispiel
public static void main(String[] args) {
run();
}
static void run() {
int result = sum(1, 2);
System.out.println(result);
}
static int sum(int a, int b) {
return a + b;
}
Wenn Sie das Programm ausführen main () wird aufgerufen, run () wird aufgerufen, sum () wird aufgerufen, System.out.println () wird aufgerufen usw., während die Prozesse einzeln ausgeführt werden. Gehen. Ein Thread ist derjenige, der die Verarbeitung ausführt, während er diesem geraden Pfad folgt.
Zum Beispiel, wenn Sie den Prozess von der Hauptfunktion aus ausführen ...
public static void main(String[] args) {
Thread currentThread = Thread.currentThread(); //Holen Sie sich Ihren eigenen Thread
System.out.printf("ID:%d, Name:%s, Priority:%d, State:%s%n",
currentThread.getId(),
currentThread.getName(),
currentThread.getPriority(),
currentThread.getState());
}
Ausführungsergebnis
ID:1, Name:main, Priority:5, State:RUNNABLE
Sie können sehen, dass es in einem Thread namens "main" ausgeführt wurde
Verzweigen Sie einen anderen Thread vom Hauptthread und versuchen Sie, etwas asynchron auszuführen.
Neu die Thread
Klasse und call start ()
.
public class Sample {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> { //Erstelle einen Thread. Übergeben Sie den Prozess, den Sie ausführen möchten, an den Konstruktor
for (int i = 1; i < 5; i++) {
System.out.println("thread: " + i);
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
return;
}
}
});
System.out.println("main: 1");
thread.start(); //Starten Sie die Verarbeitung des Threads
System.out.println("main: 2");
Thread.sleep(150L);
System.out.println("main: 3");
thread.join(); //Warten Sie auf das Ende des Threads (Wenn Sie nicht warten, gibt es kein Problem, wenn Sie es nicht tun)
System.out.println("main: 4");
}
}
Ausgabeergebnis
main: 1
main: 2
thread: 1
thread: 2
main: 3
thread: 3
thread: 4
main: 4
Sie können sehen, dass die Verarbeitung des Hauptthreads und die Verarbeitung des generierten Threads unabhängig voneinander ausgeführt werden.
Java verarbeitet Threads über die Klasse "Thread". Wenn Sie sich die Eigenschaften der Thread-Klasse in Intellij ansehen, sieht es so aus
Ich werde nur die erklären, die Sie oft sehen.
ID :long
Ein langer Typwert, der automatisch zugewiesen wird, wenn ein Thread erstellt wird. Einzigartig und unveränderlich.
name :String
Der Name des Threads.
Jeder Name kann mit setName (String)
gesetzt werden.
Wenn Sie einen Thread mit "new Thread ()" erstellen, werden Namen wie "Thread-1" und "Thread-2" willkürlich festgelegt.
state :Thread.State
Thread-Status. "Laufen" oder "Warten". Der Thread hat einen Status und befindet sich in einem der folgenden Status: "NEW", "RUNNABLE", "BLOCKED", "WAITING", "TIMED_WAITING", "TERMINATED".
Weitere Informationen finden Sie unter Javadoc.
interrupted :boolean
Ob der Thread unterbrochen wurde.
--Dieser Wert kann mit Thread # interrupt ()
auf true gesetzt werden
priority :int
Thread-Priorität.
Wenn ein Ressourcenkonflikt auftritt, wird der Thread mit der höheren Priorität mit Priorität ausgeführt.
Der Standardwert ist 5 (Thread.NORM_PRIORITY
), der niedrigste ist 1 ( Thread.MIN_PRIORITY
) und der höchste ist 10 (Thread.MAX_PRIORITY
).
Kann mit setPriority (int)
geändert werden.
daemon: boolean
Ist es ein Daemon-Thread?
Wenn daemon`` true
ist, wird es als Daemon-Thread bezeichnet, und wenn es false
ist, wird es als User-Thread bezeichnet.
Der Standardwert ist "false", der mit "setDaemon (boolean)" festgelegt werden kann.
Es gibt viele Möglichkeiten, ein Programm zu schreiben, das etwas in einem separaten Thread ausführt.
Der Thread wird gestartet, indem der auszuführende Prozess in das Konstruktorargument von "Thread" mit Lambda oder "Neu" gesetzt und "Start ()" aufgerufen wird.
Thread thread = new Thread(() -> {
//Etwas zu verarbeiten...
});
thread.start(); //Starten Sie einen Thread. "Etwas" wird asynchron ausgeführt
Sie können Thread
erben und run
überschreiben.
(Ich persönlich empfehle jedoch die Methode ↑, da die Verarbeitung von der Thread-Klasse abhängt.)
class MyThread extends Thread {
@Override
public void run() {
//Etwas zu verarbeiten...
}
}
MyThread thread = new MyThread();
thread.start(); //Starten Sie einen Thread. "Etwas" wird asynchron ausgeführt
Sie können ganz einfach so etwas wie einen Thread-Pool erstellen.
ExecutorService threadPool = Executors.newFixedThreadPool(3); //Anzahl der Themen=Erstellen Sie 3 Thread-Pools
//Versuchen Sie, 100 zu verarbeiten
for (int i = 0; i < 100; i++) {
threadPool.submit(() -> { //threadPool verwendet 3 Threads vollständig, um die Eingabeverarbeitung stetig auszuführen
//Etwas zu verarbeiten...
});
}
//Warten Sie, bis alle eingereichten Verarbeitungen abgeschlossen sind
threadPool.awaitTermination(1, TimeUnit.MINUTES);
//Thread-Pool stoppen
threadPool.shutdown();
Neben "Executors.newFixedThreadPool ()" gibt es noch viele andere Dinge.
newCachedThreadPool()
newFixedThreadPool()
newScheduledThreadPool()
newSingleThreadExecutor()
newWorkStealingPool()
Es ist wie Future / Promise in JavaScript. Interner Executor wird zur Thread-Steuerung verwendet
//Verarbeitung asynchron ausführen
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//Etwas zu verarbeiten...
});
//Sie können einen Rückruf im Rückgabewert CompletableFuture registrieren
future.whenComplete((aVoid, throwable) -> { //Im JavaScript-Versprechen.then()
//Dies wird aufgerufen, wenn "etwas getan wird"
// -Wenn "etwas" normal abgeschlossen ist, ist das auslösbare Argument null.
// -Wenn eine Ausnahme in "etwas" auftritt, wird die Ausnahme an das Argument throwable übergeben.
});
Verwenden Sie "Thread # Interrupt ()", wenn Sie die Verarbeitung eines laufenden Threads unterbrechen möchten
Thread thread = createNanikanoThread();
thread.start(); //Führen Sie den Thread aus
...
thread.interrupt(); //Senden Sie einen Suspend-Befehl an einen laufenden Thread
Nur weil Interrupt ()
bedeutet dies nicht, dass der Ziel-Thread sofort gestoppt wird!
Was passiert, wenn Sie diese Methode aufrufen, ist
Ein Bild, in dem "true" in dem booleschen Feld "unterbrochen" des Zielthreads gesetzt ist (← etwas grobe Erklärung).
Grundsätzlich müssen Sie dieses "unterbrochene" Flag im Prozess auf der unterbrochenen Seite überprüfen.
Eine möglicherweise unterbrochene Verarbeitung muss vor diesem Hintergrund implementiert werden. Sie können mit Thread.interrupted () überprüfen, ob es unterbrochen wurde (ob das Flag "unterbrochen" aktiviert ist).
//Der Prozess, etwas für immer zu tun
while (true) {
if (Thread.interrupted()) { //Überprüfen Sie, ob es unterbrochen wurde (* Wenn diese Methode aufgerufen wird, kehrt das unterbrochene Flag zu false zurück.)
throw new InterruptedException(); //Wirf eine Ausnahme aus und beende den Prozess. Grundsätzlich ist es in Ordnung, wenn Sie InterruptedException verwenden
}
//Etwas verarbeiten
...
}
Durch Aufrufen von "Thread.interrupted ()" zur Überprüfung des Status wird das unterbrochene Flag auf "false" zurückgesetzt.
(Übrigens, wenn Sie mit Thread.currentThread (). IsInterrupted ()
überprüfen, wird es nicht zurückgesetzt)
Einige Methoden überprüfen den Status "unterbrochen". Zum Beispiel wird "Thread.sleep ()" aufhören zu schlafen und eine "InterruptedException" auslösen, wenn das Flag "Interrupted" während des Schlafes gesetzt wird. (Übrigens wird das unterbrochene Flag auch zu diesem Zeitpunkt auf false zurückgesetzt.)
//Der Prozess, etwas für immer zu tun
while (true) {
Thread.sleep(1000L); //Unterbricht die Verarbeitung für 1 Sekunde. InterruptedException wird ausgelöst, wenn es im Ruhezustand unterbrochen wird
...
}
Die Tatsache, dass eine InterruptedException ausgelöst wurde, bedeutet, dass der Thread unterbrochen wurde. Eine angemessene Verarbeitung muss erfolgen, ohne dass diese Informationen verloren gehen.
Ich ignoriere die Information, dass der Thread unterbrochen wurde und fahre fort
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
Die, die du oft siehst
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
Die Information, dass der Thread unterbrochen wurde, ist verloren gegangen. Wenn diese Ausnahme im äußeren Prozess abgefangen wird, wird sie als unerwarteter Fehler behandelt.
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt(); // Here!
throw new RuntimeException(ex);
}
Die Beurteilung des unterbrochenen Flags bleibt der externen Verarbeitung überlassen. Die Information, dass es unterbrochen wurde, bleibt erhalten. Natürlich muss der Prozess, dies von außen zu erfassen, etwas tun, um festzustellen, ob es unterbrochen wurde.
(Ich weiß nicht, ob diese Methode gut ist. Bitte lassen Sie mich wissen, ob es einen besseren Weg gibt ...)
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
throw new InterruptedRuntimeException(ex);
}
Stellen Sie sicher, dass Sie diese InterruptedRuntimeException in der äußeren Verarbeitung abfangen und die entsprechende Verarbeitung durchführen.
Da es schwierig ist, jedes Mal zu versuchen, im Schlaf zu fangen, mache ich eine Utility-Klasse
public class ThreadUtils {
/**
* @param n Ruhezeit (Millisekunden)
* @löst InterruptedRuntimeException aus Wenn der Thread unterbrochen wird
*/
public static void sleep(long n) {
try {
Thread.sleep(n);
} catch (InterruptedException ex) {
throw new InterruptedRuntimeException(ex);
}
}
/**
*Überprüfen Sie, ob der aktuelle Thread unterbrochen wurde.
* @löst InterruptedRuntimeException aus Wenn der Thread unterbrochen wird
*/
public static void checkForInterruption() {
if (Thread.interrupted()) {
throw new InterruptedRuntimeException(ex);
}
}
}
WIP
Recommended Posts