Wie verwende ich Java Executor richtig?

8

Ich habe Java-Executoren in meinen Multithreading-Apps verwendet, aber ich kann nicht herausfinden, wann ich die folgenden Möglichkeiten am besten nutzen kann:

1.

%Vor%

2.

%Vor%

3.

%Vor%

Genauer gesagt, in [2] was passiert, wenn ich das doneSignal überspringe, dann ist es wie [1], also was nützt das doneSignal?

Auch in [3], was ist, wenn ich ein doneSignal-Objekt hinzufüge? Oder ist es möglich?

Was ich gerne wissen würde: Sind diese Ansätze austauschbar oder gibt es eine bestimmte Situation, in der ich einen bestimmten Typ verwenden soll?

    
Frank 08.11.2015, 16:19
quelle

1 Antwort

10
  1. ExecutorService

    ExecutorService executor=Executors.newFixedThreadPool(50);

    Es ist einfach und benutzerfreundlich. Es verbirgt Low-Level-Details von ThreadPoolExecutor .

    Dies bevorzugen Sie, wenn die Anzahl der Callable/Runnable -Tasks klein ist und das Stapeln von Aufgaben in der unbounded-Warteschlange den Speicher & amp; verschlechtern die Leistung des Systems. Wenn Sie CPU/Memory -Einschränkungen haben, verwenden Sie ThreadPoolExecutor mit Kapazitätsbeschränkungen & amp; RejectedExecutionHandler , um die Ablehnung von Aufgaben zu behandeln.

  2. CountDownLatch

    Sie haben CountDownLatch mit einer bestimmten Anzahl initialisiert. Diese Anzahl wird durch Aufrufe der Methode countDown() dekrementiert. Ich nehme an, dass Sie später in Ihrer ausführbaren Aufgabe Dekrement aufrufen. Threads, die darauf warten, dass diese Anzahl Null erreicht, können eine der Methoden await() aufrufen. Der Aufruf von await() blockiert den Thread, bis die Anzahl Null erreicht. Diese Klasse ermöglicht es einem Java-Thread zu warten, bis andere Threads ihre Aufgaben abgeschlossen haben.

    Anwendungsfälle:

    1. Maximale Parallelität erreichen: Manchmal möchten wir mehrere Threads gleichzeitig starten, um maximale Parallelität zu erreichen

    2. Warten Sie, bis die N Threads abgeschlossen sind, bevor Sie die Ausführung starten

    3. Deadlock-Erkennung.

      Sehen Sie sich diesen Artikel an von Lokesh Gupta für weitere Details.

  3. ThreadPoolExecutor : Er bietet mehr Kontrolle für die Feinabstimmung verschiedener Funktionen Thread-Pool-Parameter. Wenn Ihre Anwendung durch die Anzahl der aktiven Runnable/Callable -Tasks eingeschränkt ist, sollten Sie die beschränkte Warteschlange verwenden, indem Sie die maximale Kapazität festlegen. Sobald die Warteschlange die maximale Kapazität erreicht hat, können Sie Abweisungs-Handler definieren. Java bietet vier Arten von RejectedExecutionHandler Richtlinien .

    1. In der Standardeinstellung ThreadPoolExecutor.AbortPolicy gibt der Handler beim Zurückweisen eine Runtime RejectedExecutionException aus.

    2. In ThreadPoolExecutor.CallerRunsPolicy führt der Thread, der execute ausführt, die Task aus. Dies bietet einen einfachen Feedback-Kontrollmechanismus, der die Geschwindigkeit, mit der neue Aufgaben gesendet werden, verlangsamt.

    3. In ThreadPoolExecutor.DiscardPolicy wird eine Aufgabe, die nicht ausgeführt werden kann, einfach gelöscht.

    4. Wenn in ThreadPoolExecutor.DiscardOldestPolicy der Executor nicht heruntergefahren wird, wird die Task am Anfang der Arbeitswarteschlange gelöscht, und dann wird die Ausführung wiederholt (was wiederum fehlschlagen kann und dazu führt, dass dies wiederholt wird.)

      Wenn Sie CountDownLatch behavior simulieren möchten, können Sie invokeAll() method verwenden.

  4. Ein weiterer Mechanismus, den Sie nicht angegeben haben, ist ForkJoinPool

    Das ForkJoinPool wurde Java in Java 7 hinzugefügt. Das ForkJoinPool ist ähnlich das Java ExecutorService , aber mit einem Unterschied. Das ForkJoinPool macht es leicht für Aufgaben, ihre Arbeit in kleinere Aufgaben aufzuteilen, die dann sind auch an die ForkJoinPool gesendet. Das Stehlen von Aufgaben geschieht in ForkJoinPool , wenn freie Worker-Threads Aufgaben aus der belegten Worker-Thread-Warteschlange stehlen.

    Java 8 hat eine weitere API in ExecutorService eingeführt Arbeitsstehlen Pool erstellen. Sie müssen RecursiveTask und RecursiveAction nicht erstellen, können aber ForkJoinPool verwenden.

    %Vor%
      

    Erstellt einen Work-Stealing-Threadpool mit allen verfügbaren Prozessoren als Zielparallelitätsebene.

    Standardmäßig wird die Anzahl der CPU-Kerne als Parameter benötigt.

All diese vier Mechanismen ergänzen sich gegenseitig. Abhängig von der Granularität, die Sie steuern möchten, müssen Sie die richtigen auswählen.

    
Ravindra babu 08.11.2015, 16:33
quelle