Heim > Java > javaLernprogramm > So verwenden Sie den Java-Thread-Pool zur Optimierung unserer Anwendungen

So verwenden Sie den Java-Thread-Pool zur Optimierung unserer Anwendungen

WBOY
Freigeben: 2023-04-30 22:13:05
nach vorne
941 Leute haben es durchsucht

Thread-Pool ist ein Tool, aber nicht für alle Szenarien geeignet. Wenn wir Thread-Pools verwenden, müssen wir diese entsprechend der Art der Anwendung, der Verfügbarkeit von Rechenressourcen und den Anforderungen der Anwendung entsprechend konfigurieren. Wenn der Thread-Pool nicht ordnungsgemäß konfiguriert ist, kann dies zu einer Verschlechterung der Anwendungsleistung oder zu Problemen wie Deadlock und Hunger führen. Daher müssen wir den Thread-Pool sorgfältig auswählen.

Thread-Pool zur Optimierung von Anwendungsnutzungsszenarien verwenden

  • Eine große Anzahl kurzfristiger Aufgaben: Wenn Die Anwendung Wenn eine große Anzahl kurzfristiger Aufgaben verarbeitet werden muss, kann durch die Verwendung eines Thread-Pools die häufige Erstellung und Zerstörung von Threads vermieden werden, wodurch der Overhead beim Thread-Kontextwechsel verringert und die Leistung und Skalierbarkeit der Anwendung verbessert wird.

  • Gleichzeitiger Zugriff auf die Datenbank: Wenn die Anwendung gleichzeitig auf die Datenbank zugreifen muss, kann durch Verwendung des Thread-Pools die Rechenleistung der Multi-Core-CPU voll ausgenutzt werden und die Leistung und den Durchsatz des gleichzeitigen Zugriffs auf die Datenbank verbessern.

  • Rechenintensive Aufgaben: Wenn die Anwendung rechenintensive Aufgaben ausführen muss, kann der Thread-Pool verwendet werden, um die Aufgaben gleichzeitig auszuführen und so die Rechenleistung voll auszunutzen Leistung der Multi-Core-CPU und Verbesserung der Leistung und Reaktionsfähigkeit bei rechenintensiven Aufgaben.

  • Ereignisgesteuerte Anwendungen: Wenn die Anwendung ereignisgesteuert ist, kann die Verwendung eines Thread-Pools verhindern, dass der Ereignisverarbeitungsthread blockiert wird, und die Reaktionsgeschwindigkeit und den Durchsatz verbessern Ereignisverarbeitung.

  • Aufgaben mit langer Laufzeit: Wenn die Anwendung Aufgaben mit langer Laufzeit verarbeiten muss, kann durch die Verwendung des Thread-Pools vermieden werden, dass Thread-Ressourcen längere Zeit belegt werden, und die Verfügbarkeit verbessert werden die Anwendung und Skalierbarkeit.

Verschiedene Konfigurationen des Thread-Pools, unter welchen Umständen sollte er verwendet werden :

1.FixedThreadPool #🎜 🎜#

FixedThreadPool ist ein Thread-Pool fester Größe, der beim Erstellen eine bestimmte Anzahl von Threads vorab erstellt. Wenn eine Aufgabe ausgeführt werden muss, wählt der Thread-Pool einen verfügbaren Thread aus, um die Aufgabe auszuführen. Wenn alle Threads Aufgaben ausführen, warten neue Aufgaben in der Aufgabenwarteschlange.

Bei der Verwendung von FixedThreadPool ist vor allem die Größe des Thread-Pools zu berücksichtigen. Wenn die Thread-Poolgröße zu klein ist, kann dies dazu führen, dass Aufgaben in der Warteschlange eingereiht werden, was sich auf die Antwortzeit der Anwendung auswirkt. Wenn der Thread-Pool zu groß ist, verbraucht er möglicherweise zu viele Rechenressourcen und führt zu einer Verschlechterung der Anwendungsleistung. Daher müssen Sie bei der Auswahl der Thread-Poolgröße die Rechenanforderungen Ihrer Anwendung und die Verfügbarkeit von Rechenressourcen berücksichtigen.

2.CachedThreadPool

CachedThreadPool ist ein Thread-Pool mit dynamischer Größe, der die Größe des Thread-Pools automatisch an die Anzahl der Aufgaben anpasst. Wenn eine Aufgabe ausgeführt werden muss, erstellt der Thread-Pool einen neuen Thread, um die Aufgabe auszuführen. Wenn mehrere Aufgaben ausgeführt werden müssen, erstellt der Thread-Pool mehrere Threads. Wenn Threads inaktiv sind, recycelt der Thread-Pool diese Threads.

CachedThreadPool eignet sich für Szenarien, in denen eine große Anzahl von Aufgaben in kurzer Zeit ausgeführt werden muss. Da die Größe des Thread-Pools dynamisch an die Anzahl der Aufgaben angepasst werden kann, können Rechenressourcen besser genutzt und dadurch die Leistung der Anwendung verbessert werden.

3.SingleThreadExecutor

SingleThreadExecutor ist ein Thread-Pool mit nur einem Thread. Wenn eine Aufgabe ausgeführt werden muss, verwendet der Thread-Pool einen eindeutigen Thread, um die Aufgabe auszuführen. Wenn mehrere Aufgaben ausgeführt werden müssen, warten diese in der Aufgabenwarteschlange. Da es nur einen Thread gibt, eignet sich SingleThreadExecutor für Szenarien, die eine sequentielle Ausführung von Aufgaben erfordern, z. B. Datenbankverbindungspools oder Protokollprozessoren.

4.ScheduledThreadPool

ScheduledThreadPool ist ein Thread-Pool, der zum Ausführen geplanter Aufgaben verwendet wird. Es kann Aufgaben in festgelegten Intervallen oder nach einer festen Verzögerung ausführen. Beispielsweise können Sie ScheduledThreadPool verwenden, um Ihre Datenbank regelmäßig zu sichern oder Ihre Protokolle zu bereinigen.

Bei Verwendung von ScheduledThreadPool müssen Sie auf die Ausführungszeit der Aufgabe und die Wiederholung der Aufgabe achten. Wenn die Ausführung einer Aufgabe lange dauert, kann sich dies auf die Ausführungszeit anderer Aufgaben auswirken. Wenn die Aufgabe nicht wiederkehrend ist, müssen Sie sie möglicherweise manuell abbrechen, um zu verhindern, dass die Aufgabe fortgesetzt wird.

5.WorkStealingThreadPool

WorkStealingThreadPool ist ein Thread-Pool, der einen Work-Stealing-Algorithmus verwendet. Es verwendet mehrere Thread-Pools mit jeweils einer Aufgabenwarteschlange. Wenn ein Thread in einem Thread-Pool inaktiv ist, stiehlt er Aufgaben aus Aufgabenwarteschlangen in anderen Thread-Pools zur Ausführung.

WorkStealingThreadPool eignet sich für Szenarien, in denen mehrere unabhängige Aufgaben ausgeführt werden müssen. Da es Aufgaben und Threads dynamisch zuweist, ermöglicht es eine bessere Nutzung der Rechenressourcen und verbessert dadurch die Anwendungsleistung.

Die oben genannten sind einige häufig verwendete Thread-Pools. Natürlich bietet Java auch andere Thread-Pools wie ForkJoinPool, CachedThreadExecutor usw. Bei der Auswahl eines Thread-Pools müssen wir eine Auswahl basierend auf den Anforderungen der Anwendung und der Verfügbarkeit von Rechenressourcen treffen.

Benutzerdefinierte Erstellung eines Thread-Pools

Verwenden Sie die Executors-Factory-Klasse, um einen Thread-Pool zu erstellen. Obwohl diese Methode einfach und schnell ist, müssen wir manchmal das Verhalten des Thread-Pools genauer steuern und dann einen benutzerdefinierten Thread-Pool erstellen.

Der Thread-Pool in Java wird über die ThreadPoolExecutor-Klasse implementiert, sodass wir den Thread-Pool anpassen können, indem wir ein ThreadPoolExecutor-Objekt erstellen. Der Konstruktor der ThreadPoolExecutor-Klasse verfügt über mehrere Parameter. Hier stellen wir nur einige häufig verwendete Parameter vor.

  • corePoolSize: Die Anzahl der Kernthreads im Thread-Pool, d. h. die Mindestanzahl der Threads, die im Thread-Pool aktiv bleiben. Wenn beim Senden einer Aufgabe die Anzahl der aktiven Threads geringer ist als die Anzahl der Kern-Threads, werden neue Threads zur Verarbeitung der Aufgabe erstellt.

  • maximumPoolSize: Die maximal zulässige Anzahl von Threads im Thread-Pool. Wenn beim Senden einer Aufgabe die Anzahl der aktiven Threads die Anzahl der Kern-Threads erreicht hat und die Aufgabenwarteschlange voll ist, werden neue Threads erstellt, um die Aufgabe zu verarbeiten, bis die Anzahl der aktiven Threads die maximale Anzahl an Threads erreicht.

  • keepAliveTime: Die Zeit, die inaktive Threads von Nicht-Kern-Threads aktiv bleiben. Wenn die Anzahl der aktiven Threads größer ist als die Anzahl der Kern-Threads und die Überlebenszeit des Leerlauf-Threads keepAliveTime überschreitet, wird er zerstört, bis die Anzahl der aktiven Threads die Anzahl der Kern-Threads nicht überschreitet.

  • workQueue: Aufgabenwarteschlange, die zum Speichern von Aufgaben verwendet wird, die auf ihre Ausführung warten. Java bietet mehrere Arten von Aufgabenwarteschlangen, z. B. SynchronousQueue, LinkedBlockingQueue, ArrayBlockingQueue usw.

  • threadFactory: wird zum Erstellen neuer Threads verwendet. Sie können die Thread-Erstellungsmethode anpassen, indem Sie die ThreadFactory-Schnittstelle implementieren, z. B. den Thread-Namen festlegen, die Thread-Priorität festlegen usw.

Individuell erstellte Thread-Pools können das Verhalten des Thread-Pools flexibler steuern, z. B. die Anzahl der Kernthreads und die maximale Anzahl von Threads entsprechend unterschiedlichen Anwendungsszenarien anpassen, verschiedene Arten von Aufgabenwarteschlangen auswählen usw. Gleichzeitig müssen Sie auch auf die Designprinzipien des Thread-Pools achten, um zu vermeiden, dass zu viele Threads erstellt werden, was zu einer Verschwendung von Systemressourcen oder einem Thread-Wettbewerb führt, der zu Leistungseinbußen führt.

Thread-Pool-Optimierungsstrategien Wenn Sie Thread-Pools zur Optimierung der Anwendungsleistung verwenden, müssen Sie einige Optimierungsstrategien beachten, darunter Thread-Pool-Größe, Aufgabenwarteschlangentyp, Thread-Pool-Ausnahmebehandlung, Thread-Pool-Überwachung usw.

  • Thread-Pool-Größe: Die Größe des Thread-Pools muss basierend auf den spezifischen Anforderungen der Anwendung bestimmt werden. Wenn die Anwendung eine große Anzahl kurzfristiger Aufgaben verarbeiten muss, können Sie eine kleinere Thread-Pool-Größe festlegen. Wenn die Anwendung rechenintensive Aufgaben verarbeiten muss, können Sie eine größere Thread-Pool-Größe festlegen.

  • Typ der Aufgabenwarteschlange: Der Typ der Aufgabenwarteschlange muss ebenfalls basierend auf den spezifischen Anforderungen der Anwendung bestimmt werden. Wenn die Anzahl der Aufgaben groß ist, aber die Ausführungszeit jeder Aufgabe kurz ist, kann eine unbegrenzte Warteschlange verwendet werden. Wenn die Anzahl der Aufgaben klein ist, aber die Ausführungszeit jeder Aufgabe lang ist, kann eine begrenzte Warteschlange verwendet werden.

  • Thread-Pool-Ausnahmebehandlung: Aufgaben im Thread-Pool können Ausnahmen auslösen, und eine entsprechende Ausnahmebehandlung ist erforderlich, um zu verhindern, dass andere Aufgaben im Thread-Pool beeinträchtigt werden. Sie können Try-Catch-Blöcke verwenden, um von Aufgaben ausgelöste Ausnahmen abzufangen und entsprechend zu behandeln, z. B. durch Protokollierung, erneute Übermittlung von Aufgaben usw.

  • Thread-Pool-Überwachung: Die Thread-Pool-Überwachung kann uns dabei helfen, den Status und die Leistung des Thread-Pools zu verstehen und eine entsprechende Optimierung vorzunehmen. Sie können JMX (Java Management Extensions) oder benutzerdefinierte Überwachungskomponenten verwenden, um den Ausführungsstatus des Thread-Pools zu überwachen, z. B. die Anzahl der aktiven Threads im Thread-Pool, die Anzahl der Aufgaben in der Aufgabenwarteschlange, die Anzahl der abgeschlossenen Aufgaben, usw.

Im Folgenden gehen wir ein Beispiel durch, um zu demonstrieren, wie Sie einen Thread-Pool verwenden, um die Leistung Ihrer Anwendung zu optimieren .

Beispiel: Berechnung der Fibonacci-Folge

Wir demonstrieren anhand eines einfachen Beispiels, wie Sie einen Thread-Pool zur Berechnung der Fibonacci-Folge verwenden, um zu zeigen, wie Thread-Pools die Leistung Ihrer Anwendung verbessern können.

Die Fibonacci-Folge ist eine rekursiv definierte Folge, die wie folgt definiert ist:

  • F(0) = 0

  • F(1) = 1

  • F(n) = F(n- 1) + F(n-2), n > 1

Wir können den rekursiven Algorithmus zur Berechnung der Fibonacci-Folge verwenden, aber der rekursive Algorithmus ist weniger effizient, da er einige Werte wiederholt berechnet. Zum Beispiel erfordert die Berechnung von F(5) die Berechnung von F(4) und F(3), die Berechnung von F(4) erfordert die Berechnung von F(3) und F(2) und die Berechnung von F(3) erfordert die Berechnung von F(2) und F(1) ist ersichtlich, dass F(3) und F(2) zweimal berechnet werden.

Wir können den Thread-Pool verwenden, um wiederholte Berechnungen zu vermeiden und so die Leistung der Anwendung zu verbessern. Die spezifischen Implementierungsschritte lauten wie folgt:

  • Teilen Sie die Aufgabe in mehrere Unteraufgaben auf, und jede Unteraufgabe berechnet den Wert einer Fibonacci-Folge.

  • Unteraufgaben zur gleichzeitigen Ausführung an den Thread-Pool senden.

  • Verwenden Sie ConcurrentHashMap, um bereits berechnete Werte zwischenzuspeichern und so wiederholte Berechnungen zu vermeiden.

  • Warten Sie, bis alle Aufgaben abgeschlossen sind und Ergebnisse zurückgegeben werden.

Das Folgende ist der Implementierungscode:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class FibonacciTask extends RecursiveTask<Integer> {
    private static final long serialVersionUID = 1L;
    private static final Map<Integer, Integer> cache = new ConcurrentHashMap<>();
    private final int n;

    public FibonacciTask(int n) {
        this.n = n;
    }

    @Override
    protected Integer compute() {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        Integer result = cache.get(n);
        if (result != null) {
            return result;
        }
        FibonacciTask f1 = new FibonacciTask(n - 1);
        FibonacciTask f2 = new FibonacciTask(n - 2);
        f1.fork();
        f2.fork();
        result = f1.join() + f2.join();
        cache.put(n, result);
        return result;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ForkJoinPool pool = new ForkJoinPool();
        FibonacciTask task = new FibonacciTask(10);
        System.out.println(pool.invoke(task));
    }
}
Nach dem Login kopieren

Im obigen Code verwenden wir ForkJoinPool als Thread-Pool. Jede Unteraufgabe berechnet den Wert einer Fibonacci-Sequenz und verwendet ConcurrentHashMap, um den berechneten Wert zwischenzuspeichern, um Wiederholungszählungen zu vermeiden. Warten Sie abschließend, bis alle Aufgaben abgeschlossen sind, und geben Sie die Ergebnisse zurück.

Wir können sehen, dass wir im obigen Beispiel ForkJoinPool als Thread-Pool verwenden und die RecursiveTask-Klasse erben, um die gleichzeitige Berechnung der Fibonacci-Folge zu implementieren. In der Methode „compute()“ prüfen wir zunächst, ob der Wert der Fibonacci-Folge im Cache berechnet wurde. Wenn er berechnet wurde, wird das Ergebnis im Cache direkt zurückgegeben. Andernfalls erstellen wir zwei Unteraufgaben f1 und f2, senden sie zur gleichzeitigen Ausführung an den Thread-Pool, warten mit der Methode join () auf ihre Ausführungsergebnisse und fügen ihre Ausführungsergebnisse als Ausführungsergebnisse der aktuellen Aufgabe hinzu gleichzeitig hinzufügen Die Werte der Bonacci-Folge und ihre Berechnungsergebnisse werden im Cache gespeichert, sodass die Ergebnisse bei der nächsten Berechnung direkt aus dem Cache abgerufen werden können.

In der main()-Methode erstellen wir ein ForkJoinPool-Objekt und ein FibonacciTask-Objekt, rufen dann die invoke()-Methode auf, um die Aufgabe auszuführen und die Ausführungsergebnisse auf der Konsole auszugeben.

Anhand dieses einfachen Beispiels können wir sehen, dass die Verwendung eines Thread-Pools die Leistung einer Anwendung erheblich verbessern kann, insbesondere bei rechenintensiven Aufgaben. Der Thread-Pool kann Aufgaben gleichzeitig ausführen und so die Rechenleistung von Multi-Core-CPUs voll ausnutzen, wodurch die häufige Erstellung und Zerstörung von Threads vermieden wird, wodurch die Kosten für den Thread-Kontextwechsel gesenkt und die Anwendungsleistung und Skalierbarkeit verbessert werden.

Das obige ist der detaillierte Inhalt vonSo verwenden Sie den Java-Thread-Pool zur Optimierung unserer Anwendungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage