Ich habe ein Java-Programm erstellt, in dem mehrere Threads parallel auf die Datenbank zugreifen. Es stellte sich jedoch heraus, dass mit zunehmender Anzahl von Threads die Obergrenze der von DBMS festgelegten DB-Verbindung überschritten wurde und das Programm einfriert.
Verwenden Sie ExecutorService, um die maximale Anzahl von Threads zu begrenzen.
ExecutorService ist eine Schnittstelle, die im Paket "java.util.concurrent" der Java-Standard-Parallelverarbeitungsbibliothek enthalten ist und Java-Threads umschließt, die nur schwer roh zu verwenden sind, und deren Verwendung vereinfacht.
■ ExecutorService
Weitere Informationen finden Sie unter Java 8 API Specification ExecutorService.
Schreiben Sie zuerst einen Thread. Die eigentliche Verarbeitung wird nicht durchgeführt, aber um den Anschein zu erwecken, dass die Verarbeitung lange dauert, schlafen Sie für die durch das Argument angegebene Zeit und beenden Sie dann.
SampleThread.java
package sample;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class SampleThread implements Runnable {
private int no;
private int time;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
SampleThread(int no, int time) {
this.no = no;
this.time = time;
}
@Override
public void run() {
System.out.println(" No." + no + " start id:" + Thread.currentThread().getId() + "Überlebenszeit:" + time + "Aktuelle Uhrzeit:" + sdf.format(Calendar.getInstance().getTime()));
try {
//Legen Sie es in den Schlaf, um so zu tun, als ob etwas passiert.
Thread.sleep(time * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" No." + no + " end id:" + Thread.currentThread().getId() + "Überlebenszeit:" + time + "Aktuelle Uhrzeit:" + sdf.format(Calendar.getInstance().getTime()));
}
}
Verwenden Sie als Nächstes ExecutorService und versuchen Sie, den zuvor geschriebenen Thread zu verwenden. Da ExecutorService eine Schnittstelle ist, müssen wir diese Schnittstelle implementieren. Hier können wir jedoch die Executors # newFixedThreadPool-Methode verwenden, um einen ExecutorService mit einem Thread-Pool abzurufen. Die Obergrenze des Thread-Pools ist der Übersichtlichkeit halber auf 3 Threads festgelegt.
Main.java
package sample;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
//Stellen Sie den maximalen Thread-Pool auf 3 Threads ein.
final int MAX_THREADS = 3;
//Erstellen Sie einen ExecutorService mit einem Thread-Pool mit der Factory-Methode "newFixedThreadPool".
ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
//Versuchen Sie, 10 Threads einzurichten
for (int i = 0; i < 10; i++) {
//Nummerieren Sie die Threads.
int no = i;
//Die Überlebenszeit des Fadens wird zufällig von 1 bis 10 Sekunden bestimmt.
int lifeTime = (int)(Math.random() * 9 + 1);
//Starten Sie einen Thread.
executor.submit(new SampleThread(no, lifeTime));
}
//Schließen Sie ExecutorService.
System.out.println("executor.shutdown();");
executor.shutdown();
}
}
Wenn das obige Testprogramm ausgeführt wird, wird Folgendes an die Konsole ausgegeben.
Artikel | Bedeutung |
---|---|
No. | Verarbeitungsnummer, die beim Starten eines Threads als Argument angegeben wird |
id | Thread-spezifische ID. |
Überlebenszeit | Die Zeit, die der Thread schläft. (Sekunden) |
Konsole
No.0 start id:12 Überlebenszeit:1 Aktuelle Zeit:13:29:41
No.1 start id:13 Überlebenszeit:8 Aktuelle Zeit:13:29:41
No.2 start id:14 Überlebenszeit:6 Aktuelle Zeit:13:29:41
executor.shutdown();
No.0 end id:12 Überlebenszeit:1 Aktuelle Zeit:13:29:42
No.3 start id:12 Überlebenszeit:1 Aktuelle Zeit:13:29:42
No.3 end id:12 Überlebenszeit:1 Aktuelle Zeit:13:29:43
No.4 start id:12 Überlebenszeit:9 Aktuelle Zeit:13:29:43
No.2 end id:14 Überlebenszeit:6 Aktuelle Zeit:13:29:47
No.5 start id:14 Überlebenszeit:2 Aktuelle Zeit:13:29:47
No.1 end id:13 Überlebenszeit:8 Aktuelle Zeit:13:29:49
No.6 start id:13 Überlebenszeit:9 Aktuelle Zeit:13:29:49
No.5 end id:14 Überlebenszeit:2 Aktuelle Zeit:13:29:49
No.7 start id:14 Überlebenszeit:7 Aktuelle Zeit:13:29:49
No.4 end id:12 Überlebenszeit:9 Aktuelle Zeit:13:29:52
No.8 start id:12 Überlebenszeit:7 Aktuelle Zeit:13:29:52
No.7 end id:14 Überlebenszeit:7 Aktuelle Zeit:13:29:56
No.9 start id:14 Überlebenszeit:4 Aktuelle Zeit:13:29:56
No.6 end id:13 Überlebenszeit:9 Aktuelle Zeit:13:29:58
No.8 end id:12 Überlebenszeit:7 Aktuelle Zeit:13:29:59
No.9 end id:14 Überlebenszeit:4 Aktuelle Zeit:13:30:00
Wenn Sie sich den Teil "Nr." Betrachten, gibt es Zahlen von 0 bis 9, und der Thread wird 10 Mal verarbeitet. Wenn Sie sich andererseits die ID des Threads ansehen, sehen Sie, dass es nur 12 bis 14 gibt und die Anzahl der Threads auf 3 begrenzt ist. Wenn die Verarbeitung eines Threads abgeschlossen ist, kann auch bestätigt werden, dass der Thread mit derselben ID bei der nächsten Verarbeitung verwendet wird. Aus diesen Dingen kann gesagt werden, dass drei Threads wiederverwendet werden. Sie können auch sehen, dass maximal 3 Threads gleichzeitig ausgeführt werden.
Die ausführbare # shutdown-Methode wird unmittelbar nach dem Start der maximalen Anzahl von 3 Threads aufgerufen. Dies liegt daran, dass, wenn der Thread die maximale Anzahl von Thread-Pools erreicht hat, die Übermittlung der Aufrufquelle des Threads nicht blockiert wird, sondern die gesamte Aufgabe selbst von der FIFO-Warteschlange akzeptiert wird. Sie können auch bestätigen, dass diese Warteschlange ordnungsgemäß funktioniert.
https://github.com/nogitsune413/ExecutorServiceSample
Java8 API Specification ExecutorService Verwendung von ExecutorService Stoppen Sie die Ausführung von Thread.start (). "ExecutorService" erleichtert die Thread-Verwaltung. Multithread-Verarbeitung in Java mit ExecutorService
Java 1.8
Recommended Posts