Begrenzen Sie die Anzahl der Threads mithilfe des Java Executor Service

Problem

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.

Lösung

Verwenden Sie ExecutorService, um die maximale Anzahl von Threads zu begrenzen.

Was ist Executor Service?

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.

Testprogramm erstellen

Faden

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()));
	}
}

ExecutorService mit Thread-Pool

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();
	}
}

Test durchführen

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

Analyse der Testergebnisse

Maximale Anzahl von Threads

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.

Der ExecutorService-Aufrufer ist nicht blockiert

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.

Beispielcode

https://github.com/nogitsune413/ExecutorServiceSample

Referenz

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

Bestätigungsumgebung

Java 1.8

Recommended Posts

Begrenzen Sie die Anzahl der Threads mithilfe des Java Executor Service
Über die Anzahl der Threads von Completable Future
Bei Verwendung des Konstruktors der Date-Klasse von Java wird das Datum um 1900 vorverlegt.
Befehl zum Überprüfen der Anzahl und des Status von Java-Threads
Ich habe versucht, die Cache-Funktion des Application Container Cloud Service zu verwenden
Versuchen Sie, || anstelle des ternären Operators zu verwenden
Versuchen Sie, den Dienst auf Android Oreo zu verwenden
So bestimmen Sie die Anzahl der Parallelen
[Java] Überprüfen Sie die Anzahl der Zeichen
Überprüfen Sie die Funktion der Schnittstelle über den Thread
[Rails] Implementierung des PV-Nummernrankings mit Impressionist
Ich habe versucht, den Profiler von IntelliJ IDEA zu verwenden
Ich habe die Anzahl der Taxis mit Ruby überprüft
[Rails] Verwenden Sie das Pulldown-Feld, um die Post-Liste nach Datum oder Anzahl der Likes zu sortieren.
Implementieren wir eine Funktion, um die Anzahl der Zugriffe auf die API mit SpringBoot + Redis zu begrenzen
Mit der Kalenderklasse von Java bleibt man am letzten Tag des Monats ein wenig hängen