Das Implementierungsprinzip von Tomcat zur Korrektur des nativen Threadpool-Fehlers des JDK

Das Implementierungsprinzip von Tomcat zur Korrektur des nativen Threadpool-Fehlers des JDK

Um die Verarbeitungsleistung und Parallelität zu verbessern, legen Webcontainer die Aufgabe der Anforderungsverarbeitung im Allgemeinen in den Threadpool. Der native Threadpool von JDK ist von Natur aus für CPU-intensive Aufgaben geeignet, daher hat Tomcat ihn geändert.

Tomcat-Thread-Pool-Prinzip

Tatsächlich weisen die Parameter von ThreadPoolExecutor hauptsächlich die folgenden Schlüsselpunkte auf:

Begrenzen Sie die Anzahl der Threads

Begrenzung der Warteschlangenlänge

Tomcat muss diese beiden Ressourcen begrenzen, da sonst bei hoher Parallelität die CPU und der Speicher erschöpft sein können.
Daher übergibt der Thread-Pool von Tomcat folgende Parameter:

// Angepasste Task-Warteschlange taskqueue = new TaskQueue(maxQueueSize);

// Angepasste Thread-Factory TaskThreadFactory tf = neue TaskThreadFactory(namePrefix,
							                 Dämon,
							                 getThreadPriority()
);

// Benutzerdefinierter Thread-Pool-Executor = neuer ThreadPoolExecutor(getMinSpareThreads(),
								  getMaxThreads(),
				 			      maxLeerlaufzeit, 
				 			      Zeiteinheit.MILLISEKUNDEN,
				 			      Aufgabenwarteschlange,
				 			      tf);

Tomcat verfügt außerdem über eine Begrenzung der Thread-Anzahl:

  • Anzahl der Kern-Threads (minSpareThreads)
  • Maximale Anzahl von Thread-Pools (maxThreads)

Der Tomcat-Thread-Pool verfügt außerdem über einen eigenen speziellen Taskverarbeitungsfluss, der durch Umschreiben der Execute-Methode seine eigene spezielle Taskverarbeitungslogik implementiert:

  1. Wenn CorePoolSize-Aufgaben vorhanden sind, wird für jede Aufgabe ein neuer Thread erstellt.
  2. Wenn weitere Aufgaben vorhanden sind, legen Sie sie in die Aufgabenwarteschlange und lassen Sie alle Threads darauf zugreifen. Wenn die Warteschlange voll ist, erstellen Sie einen temporären Thread
  3. Wenn die Gesamtzahl der Threads die maximale Poolgröße erreicht, versuchen Sie weiterhin, Aufgaben in die Aufgabenwarteschlange einzufügen
  4. Wenn auch die Pufferwarteschlange voll ist, schlägt das Einfügen fehl und die Ablehnungsstrategie wird ausgeführt

Der Unterschied zwischen Tomcat- und JDK-Threadpools liegt in Schritt 3. Wenn die Gesamtzahl der Threads die maximale Anzahl erreicht, führt Tomcat die Ablehnungsstrategie nicht sofort aus, sondern versucht, Aufgaben zur Aufgabenwarteschlange hinzuzufügen. Wenn das Hinzufügen fehlschlägt, führt es die Ablehnungsstrategie erneut aus .

Wie wird es konkret erreicht?

public void execute(Ausführbarer Befehl, langes Timeout, TimeUnit-Einheit) {
    SubmittedCount.incrementAndGet();
    versuchen {
        //Rufen Sie die Ausführungsfunktion des nativen JDK-Thread-Pools auf, um die Aufgabe auszuführen super.execute(command);
    } Fang (RejectedExecutionException rx) {
       // Wenn die Gesamtzahl der Threads maximumPoolSize erreicht, führt der native JDK-Thread-Pool die Standard-Ablehnungsrichtlinie aus, wenn (super.getQueue() instanceof TaskQueue) {
            endgültige TaskQueue-Warteschlange = (TaskQueue)super.getQueue();
            versuchen {
                // Versuchen Sie weiterhin, die Aufgabe in die Aufgabenwarteschlange zu stellen, wenn (!queue.force(command, timeout, unit)) {
                    submitCount.decrementAndGet();
                    // Wenn die Pufferwarteschlange immer noch voll ist, schlägt das Einfügen fehl und die Ablehnungsstrategie wird ausgeführt.
                    wirf eine neue RejectedExecutionException("...");
                }
            } 
        }
    }
}

Anpassen der Aufgabenwarteschlange

Die erste Zeile der Execute-Methode des Tomcat-Thread-Pools:

SubmittedCount.incrementAndGet();

Wenn eine Aufgabe fehlschlägt und eine Ausnahme ausgelöst wird, wird der Zähler um eins reduziert:

submitCount.decrementAndGet();

Der Tomcat-Thread-Pool verwendet die Variable „submitedCount“ , um die Anzahl der Aufgaben zu verwalten, die an den Thread-Pool übermittelt, aber nicht ausgeführt wurden.

Warum eine solche Variable pflegen?

Tomcats Task-Warteschlange TaskQueue erweitert JDKs LinkedBlockingQueue. Tomcat gibt ihr eine Kapazität und übergibt sie an den Konstruktor der übergeordneten Klasse LinkedBlockingQueue.

öffentliche Klasse TaskQueue erweitert LinkedBlockingQueue<Runnable> {

  öffentliche TaskQueue(int Kapazität) {
      Super(Kapazität);
  }
  ...
}

Der Kapazitätsparameter wird durch den Parameter maxQueueSize von Tomcat festgelegt, aber der Standardwert von maxQueueSize ist Integer.MAX_VALUE : Wenn die aktuelle Anzahl der Threads die Anzahl der Kern-Threads erreicht hat und eine weitere Aufgabe vorhanden ist, fügt der Thread-Pool die Aufgabe der Aufgabenwarteschlange hinzu. Sie wird immer erfolgreich ausgeführt, sodass nie die Möglichkeit besteht, einen neuen Thread zu erstellen.

Um dieses Problem zu lösen, schreibt TaskQueue LinkedBlockingQueue#offer neu und gibt zum richtigen Zeitpunkt false zurück, was darauf hinweist, dass das Hinzufügen der Aufgabe fehlgeschlagen ist. Zu diesem Zeitpunkt erstellt der Thread-Pool einen neuen Thread.

Wann ist der richtige Zeitpunkt?

öffentliche Klasse TaskQueue erweitert LinkedBlockingQueue<Runnable> {

  ...
   @Überschreiben
  // Wenn der Thread-Pool die Task-Warteschlangenmethode aufruft, ist die aktuelle Anzahl der Threads > die Anzahl der Kern-Threads public boolean offer(Runnable o) {

      // Wenn die Anzahl der Threads das Maximum erreicht hat, können keine neuen Threads erstellt werden und können nur dann in die Aufgabenwarteschlange gestellt werden, wenn (parent.getPoolSize() == parent.getMaximumPoolSize()). 
          gibt super.offer(o) zurück;
          
      // Bisher zeigt es an, dass die maximale Anzahl an Threads > die aktuelle Anzahl an Threads > die Kernanzahl an Threads ist. // Zeigt an, dass neue Threads erstellt werden können:
      
      // 1. Wenn die Anzahl der übermittelten Aufgaben < die aktuelle Anzahl der Threads ist, // bedeutet dies, dass noch inaktive Threads vorhanden sind und keine neuen Threads erstellt werden müssen, wenn (parent.getSubmittedCount()<=(parent.getPoolSize())) 
          gibt super.offer(o) zurück;
          
      // 2. Wenn die Anzahl der übermittelten Aufgaben > der aktuellen Anzahl der Threads ist // Es sind nicht genügend Threads vorhanden. Gib „false“ zurück, um einen neuen Thread zu erstellen, wenn (parent.getPoolSize()<parent.getMaximumPoolSize()) 
          gibt false zurück;
          
      // Standardmäßig die Aufgabe immer in die Aufgabenwarteschlange einfügen return super.offer(o);
  }
  
}

Daher verwaltet Tomcat die Anzahl der übermittelten Aufgaben , um dem Thread-Pool die Möglichkeit zu geben, neue Threads zu erstellen, wenn die Länge der Aufgabenwarteschlange unendlich ist.

Dies ist das Ende dieses Artikels darüber, wie Tomcat den JDK-native-Thread-Pool-Fehler behebt. Weitere Informationen zum Tomcat JDK-native-Thread-Pool finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Tomcat verwendet Thread-Pool zur Verarbeitung gleichzeitiger Remote-Anfragen
  • Detaillierte Erläuterung der Anzahl der Verbindungen und des Thread-Pools basierend auf Tomcat
  • Analyse der Anwendungsfälle von JDK-Thread-Pool und Spring-Thread-Pool
  • Detaillierte Erläuterung der Thread-Pool-Instanz von JDK

<<:  Sechs Möglichkeiten zur Steigerung der Geschwindigkeit Ihrer Website

>>:  Einführung in die Verwendung von Requisiten in Vue

Artikel empfehlen

Detaillierte Erläuterung der Winkel-Zweiwegebindung

Inhaltsverzeichnis Bidirektionales Bindungsprinzi...

Detaillierte Erklärung zur Abfrage von Feldern im JSON-Format in MySQL

Während des Entwicklungsprozesses trat eine Anfor...

Tutorial zur Installation des Tomcat-Servers unter Windows

1 Herunterladen und vorbereiten Zuerst müssen wir...

Lassen Sie Ihren Text mit dem Marquee-Attribut in HTML tanzen

Syntax: <marquee> …</marquee> Mithilfe...

MySQL-Fremdschlüsseleinschränkung (FOREIGN KEY) Fallerklärung

Die MySQL-Fremdschlüsseleinschränkung (FOREIGN KE...

Detaillierte Erklärung zur Verwendung der Clip-Path-Eigenschaft in CSS

Verwendung von Clip-Pfaden Polygon Der Wert setzt...

So benennen Sie in Linux mehrere Dateien gleichzeitig um

Vorwort In unserer täglichen Arbeit müssen wir hä...

So löschen und deinstallieren Sie MySQL in Windows 10 vollständig

Vorwort Dieser Artikel enthält eine Anleitung zum...

Tkinter verwendet JS-Canvas, um Farbverlaufsfarben zu erzielen

Inhaltsverzeichnis 1. Verwenden Sie RGB zur Darst...