Welchen ThreadPool in Java soll ich verwenden?

8

Es gibt eine große Menge an Aufgaben. Jede Aufgabe gehört zu einer einzelnen Gruppe. Die Anforderung besteht darin, dass jede Gruppe von Aufgaben seriell ausgeführt werden sollte, genauso wie sie in einem einzelnen Thread ausgeführt werden, und der Durchsatz sollte in einer Multicore- (oder Multi-CPU-) Umgebung maximiert werden. Hinweis: Es gibt auch eine große Anzahl von Gruppen, die proportional zur Anzahl der Aufgaben ist.

Die naive Lösung verwendet ThreadPoolExecutor und synchronisiert (oder sperrt). Threads würden sich jedoch gegenseitig blockieren und der Durchsatz wird nicht maximiert.

Irgendeine bessere Idee? Oder gibt es eine Drittanbieter-Bibliothek, die die Anforderung erfüllt?

    
James 15.07.2010, 07:50
quelle

5 Antworten

3

Ein einfacher Ansatz wäre es, alle Gruppenaufgaben in eine Superaufgabe zu "verketten", wodurch die Teilaufgaben seriell ausgeführt werden. Dies führt jedoch wahrscheinlich zu einer Verzögerung in anderen Gruppen, die erst gestartet werden, wenn eine andere Gruppe vollständig beendet ist und im Thread-Pool Platz findet.

Alternativ können Sie die Aufgaben einer Gruppe verketten. Der folgende Code veranschaulicht es:

%Vor%

Der Vorteil ist, dass keine zusätzliche Ressource (Thread / Queue) verwendet wird und dass die Granularität von Tasks besser ist als die im naiven Ansatz. Der Nachteil ist, dass alle Gruppenaufgaben im Voraus bekannt sein sollten .

- bearbeiten -

Um diese Lösung generisch und vollständig zu machen, möchten Sie vielleicht die Fehlerbehandlung (dh ob eine Kette fortgesetzt wird, selbst wenn ein Fehler auftritt) entscheiden, und es wäre auch eine gute Idee, ExecutorService zu implementieren und alle Aufrufe an die zugrunde liegenden Executor.

    
Eyal Schneider 15.07.2010, 08:51
quelle
2

Ich würde vorschlagen, Task-Queues zu verwenden:

  • Für jede Aufgabengruppe müssen Sie eine Warteschlange erstellen und alle Aufgaben aus dieser Gruppe einfügen.
  • Nun können alle Ihre Warteschlangen parallel ausgeführt werden, während die Aufgaben in einer Warteschlange seriell ausgeführt werden.

Eine schnelle Google-Suche legt nahe, dass die Java-API selbst keine Task- / Thread-Warteschlangen hat. Es gibt jedoch viele Tutorials zum Codieren eines. Jeder kann sich gute Tutorien / Implementierungen nennen, wenn Sie einige kennen:

    
Dave O. 15.07.2010 08:28
quelle
1

Ich stimme hauptsächlich Daves Antwort zu, aber wenn Sie die CPU-Zeit über alle "Gruppen" hinweg teilen müssen, dh alle Aufgabengruppen sollten parallel fortschreiten, könnten Sie diese Art von Konstrukt nützlich finden (Entfernen als "Sperre") hat in meinem Fall gut funktioniert, obwohl ich mir vorstelle, dass es mehr Speicher verbraucht):

%Vor%

und

%Vor%

Sie können dann die optimale Anzahl von Threads verwenden, um die Aufgabe DoWork auszuführen. Es ist eine Art Round-Robin-Lastausgleich.

Sie können sogar etwas anspruchsvolleres tun, indem Sie dies anstelle einer einfachen Warteschlange in TaskAllocator verwenden (Aufgabengruppen mit mehr verbleibenden Aufgaben werden in der Regel ausgeführt)

%Vor%

wobei SophisticatedComparator

ist %Vor%     
Enno Shioji 15.07.2010 08:48
quelle
0

Actor ist auch eine andere Lösung für diese spezielle Art von Problemen. Scala hat Schauspieler und auch Java, die von AKKA zur Verfügung gestellt werden.

    
James 14.10.2010 08:32
quelle
-2

Ich hatte ein ähnliches Problem wie Sie, und ich habe ein ExecutorCompletionService verwendet, das mit einem Executor arbeitet, um eine Sammlung von Aufgaben zu vervollständigen. Hier ist ein Auszug aus java.util.concurrent API, seit Java7:

  

Angenommen, Sie haben eine Reihe von Solvern für ein bestimmtes Problem, die jeweils einen Wert vom Typ Ergebnis zurückgeben und sie gleichzeitig ausführen möchten. Dabei werden die Ergebnisse jedes einzelnen, die in einer Methode einen Nicht-Null-Wert zurückgeben, verarbeitet Verwenden (Ergebnis r). Sie könnten dies wie folgt schreiben:

%Vor%

In Ihrem Szenario ist also jede Aufgabe eine einzige Callable<Result> und Aufgaben werden in einer Collection<Callable<Result>> gruppiert.

Referenz: Ссылка

    
Olly 28.10.2014 16:07
quelle

Tags und Links