4

In meiner Anwendung habe ich 4 verschiedene Prozesse, die permanent mit einigen kleinen Pausen ausgeführt werden.Mehrere newSingleThreadExecutor vs. newFixedThreadPool von ExecutorService

Die aktuelle Version von Code führt jeden Prozess in einem separaten Thread alte Schule:

Thread nlpAnalyzer = new Thread(() -> { 

    // infine lop for auto restore in case of crash 
    //noinspection InfiniteLoopStatement 
    while (true) { 
     try { 
      // this method should run permanently, pauses implemented internally 
      NLPAnalyzer.analyzeNLP(dbCollection); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}); 

nlpAnalyzer.setName("im_nlpAnalyzer"); 
nlpAnalyzer.start(); 

Jetzt würde ich mit der Verwendung von ExecutorService diesen Code Refactoring mag. Um dies zu tun, kann ich mindestens zwei Ansätze verwenden:

  • newFixedThreadPool(numOfProc);
  • numOfProc * newSingleThreadExecutor().

Meine Fragen:

  1. Gibt es einen Grund, warum ich eine Option auf einem anderen vorziehen sollte?
  2. Was wird mehr akzeptiert, um einen Thread-Pool mit X-Threads zu generieren oder X newSingleThreadExecutor zu generieren?
  3. Pro und Kontra von jedem der Ansatz?
+0

Option 1 ist häufiger und hat am wenigsten Aufwand. – Spotted

+0

Bei einer anderen Notiz können Sie den Code in der Endlosschleife als 'Runnable' erneut schreiben, der sich beim Ausführen als Executor-Service erneut anmeldet. Auf diese Weise können mehrere Aufgaben sogar für einen einzelnen Thread ausgeführt werden. –

Antwort

2

jede Aufgabe ist eine unendliche Schleife gegeben, verwendet, was ich möchte, ist ein

newCachedThreadPool(); 

Dieses einen Thread für jede Aufgabe schaffen würde, die es benötigt wird (und nicht mehr)

Der Vorteil Wenn Sie jeweils einen einzelnen Thread-Pool verwenden, können Sie den Pool einzeln herunterfahren oder jedem Thread einen Namen geben, aber wenn Sie das nicht benötigen, ist das nur ein Overhead.

Hinweis: Sie können den Namen eines Threads mit setName ("Meine Aufgabe") ändern, was für das Debugging/Profiling nützlich sein könnte.

Einer der Tricks bei der Verwendung eines ExecutorService ist, dass es alle nicht abgefangenen Exception/errors erfasst und in das Future Objekt zurückgibt. Oftmals wird Future verworfen, was bedeutet, dass wenn Ihre Aufgabe unerwartet abbricht, dies auch stillschweigend geschieht.

Ich schlage vor, Sie versuchen/werfen (Throwable) außerhalb der Schleife und protokollieren Sie es, so dass Sie sehen können, ob der Thread jemals unerwartet stirbt. z. B. OutOfMemoryError

+0

Soweit mir bekannt ist, kann ich auch in 'newFixedThreadPool' einen eigenen Thread-Namen vergeben, nicht nur mit' newSingleThreadExecutor'. Gibt es einen Leistungsunterschied zwischen define 1 'newFixedThreadPool' für X-Threads oder X' newSingleThreadExecutor's? –

+1

@MikeB. Sie können einen separaten Thread-Namen zuweisen, jedoch keinen, der auf dem Zweck der Aufgabe basiert, der nützlicher sein könnte. Ich würde tun, was immer du für klarer hältst, egal welche Lösung du wählst, ein 'Thread' macht immer noch die Arbeit. –

1

Ich sehe keinen Vorteil für die untere Option, außer das Herunterfahren des einzelnen Executors.

numOfProc * newSingleThreadExecutor() 

Aber Sie haben mehr Optionen. Ich bevorzuge eine von unter drei Optionen von Executors.

newFixedThreadPool 
newCachedThreadPool 
newWorkStealingPool 

Siehe unten SE Fragen für relevante Suchanfragen:

Java's Fork/Join vs ExecutorService - when to use which?

How to properly use Java Executor?

Difference between Executors.newFixedThreadPool(1) and Executors.newSingleThreadExecutor()