2016-04-05 15 views
1

Ich benutze den ForkJoinPool, um Aufgaben parallel auszuführen. Wenn ich mir den Logout-Befehl meines Programms ansehe, scheint es, dass der ForkJoinPool eine große Menge an Arbeitern erstellt, um meine Aufgaben auszuführen (es gibt Protokolleinträge, die wie folgt aussehen: 05 Apr 2016 11:39:18,678 [ForkJoinPool-2-worker-2493] <message>).ForkJoinPool erstellt eine große Menge an Arbeitern

Gibt es für jede erstellte Aufgabe einen Arbeiter, der dann entsprechend der Anzahl der Parallelitäten ausgeführt wird, die ich im ForkJoinPool konfiguriert habe, oder mache ich etwas falsch? Hier ist, wie ich es tun:

public class MyClass { 
    private static final int NUM_CORES = Runtime.getRuntime().availableProcessors(); 
    public MyClass() { 
     int maxThreads = NUM_CORES * 2; 
     this.forkJoinPool = new ForkJoinPool(maxThreads); 
    } 

    public void doStuff() { 
     final int[] toIndex = {0}; 
     forkJoinPool.submit(() -> { 
      List<ForkJoinTask> tasks = new ArrayList<>(); 
      while (toIndex[0] < objects.size()) { 
       toIndex[0] += 20; 
       List<Object> bucket = objects.subList(toIndex[0] - 20, toIndex[0]); 
       ForkJoinTask task = new UpdateAction(bucket); 
       tasks.add(task); 
       task.fork(); 
      } 
      tasks.forEach(ForkJoinTask::join); 
     }).join(); 
    } 

    private class UpdateAction extends RecursiveAction { 

     private List<Object> bucket; 

     private UpdateAction(List<Object> bucket) { 
      this.bucket = bucket; 
     } 

     @Override 
     protected void compute() { 
      // do some calculation 
     } 
    } 
} 
+0

Blick in die Quelle (GrepCode) - die Nummer ist nur ein gemeinsamer Zähler, der unter allen ForkJoinPools geteilt wird und erhöht wird, wenn ein neuer Arbeiter erstellt wird. Es spiegelt in keiner Weise die Anzahl der Threads in Ihrem ForkJoinPool wider. – Fildor

Antwort

1

Die Zahl am Ende eines Task-Namen hat nichts mit der tatsächlichen Anzahl der Threads durch den Pool zu tun. Sehen Sie sich die registerWorker-Methode der ForkJoinPool-Klasse an. Es sieht etwa so aus:

final WorkQueue registerWorker(ForkJoinWorkerThread wt) { 
    UncaughtExceptionHandler handler; 
    wt.setDaemon(true);       // configure thread 
    if ((handler = ueh) != null) 
     wt.setUncaughtExceptionHandler(handler); 
    WorkQueue w = new WorkQueue(this, wt); 
    int i = 0;         // assign a pool index 
    int mode = config & MODE_MASK; 
    int rs = lockRunState(); 
    ... 
    // some manipulations with i counter 
    ... 
    wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1))); 
    return w; 
} 

workerNamePrefix zu

"ForkJoinPool-" + nextPoolId() + "-worker-" 

initialisiert Wenn Sie die reale Anzahl der Threads durch den Pool messen wollen Sie besser log was getPoolSize() zurückkehrt.

+0

Also, wenn die Parallelität des forkJoinPool ist 8 (4 Kerne * 2), obwohl ein paar tausend Arbeiter erstellt werden nur 8 parallel ausgeführt werden? – mvieghofer

+0

@mVIEWHOFER Der Pool kann mehr als 8 Threads enthalten (wenn alle Joiner blockiert sind), aber nur 8 oder weniger laufen zu einem bestimmten Zeitpunkt. Das sagen die Kommentare in der ForkJoinPool.java-Klasse: "Wenn nicht bereits genug Live-Threads vorhanden sind, kann die Methode tryCompensate() einen Ersatz-Thread erstellen oder reaktivieren, um blockierte Joiner zu kompensieren, bis sie entsperrt werden." –

+0

danke für die Erklärung! – mvieghofer

0

Sie haben recht mit der großen Anzahl von Worker-Threads. Ich schrieb this in 2011 und es ist noch heute anwendbar. Das Framework kann keinen richtigen Join() ausführen, sodass entweder neue Worker-Threads oder Blockierungen erstellt werden.