List von mehreren Threads abarbeiten lassen

stevetc

Grünschnabel
Hi,

ich habe die Aufgabe eine List von Objekten möglichst effizient parallel abzuarbeiten zu lassen. Jedes Objekt hat bereits ein Interface bekommen, dass eine Methode (etwas vereinfacht dargestellt) definiert.
Jetzt soll von jedem Objekt die definierte Berechnungsmethode aufgerufen werden.

Ich habe es folgendermaßen gelöst:

Mein Interface:
Code:
public interface Calculatable {
    public void calculate_x();
}

Meine Liste
Code:
List<Calculatable> myList = new ArrayList<Calculatable>();

Dann ein RunnableWorker:
Code:
public class Worker implements Runnable {

    private final List<Calculatable> calculatables;
    private CyclicBarrier cyclicBarrier = null;
    private int listStartIndex = 0;
    private int listEndIndex = 0;
    
    public Worker(final  List<Calculatable> calculatables) {
        this.calculatables = calculatables;
    }

    public void setCalculatables(CyclicBarrier cyclicBarrier,
                                    final int listStartIndex, final int listEndIndex) {
        this.cyclicBarrier = cyclicBarrier;
        this.listStartIndex = listStartIndex;
        this.listEndIndex = listEndIndex;
    }

    @Override
    public void run() {
        for (int i = listStartIndex; i < listEndIndex; i++) {
            calculatables.get(i).calculate_q_out();
        }

        try {
            cyclicBarrier.await();
        }

        catch (Exception ex) {
            Logger.getLogger(QOutCalcWorker.class.getName()).log(Level.SEVERE, null, ex);
        }     
    }
}

Dann teile ich die Liste über den Start und Endindex in 4 teile auf und lasse einen ExcecutorService 4 Threads die Liste bearbeite:

Code:
    final int maxThreadNumber = 4;
    cyclicBarrierQFirstList = new CyclicBarrier(maxThreadNumber+1);
    executorServiceQFirstList =     Executors.newFixedThreadPool(maxThreadNumber);

// erstellen und intialisieren einer List<Worker> runnables mit 4 Einträgen, habe ich mal weggelassen

    for (Runnable runnableWorker : runnables) {
          executorService.execute(runnableWorker);
    }

    try {
        cyclicBarrier.await();
    }
    catch (Exception ex) {
        Logger.getLogger(Network.class.getName()).log(Level.SEVERE, "Error while waiting for a q_out_calculation runnables: ", ex);
    }

Das ganze funktioniert an sich ganz gut, ich habe jedoch das "Problem", dass falls ein Thread mal etwas länger benötigt, für seinen Listenbereich, alle anderen warten müssen, bis es weiter geht (ich benötige die CyclicBarrier, da ich das ganze sehr oft nacheinander durchlaufen lassen muss, d.h. beim 2. mal wird einfach cyclicBarrier.reset() durchgeführt und weiter gehts).

Hat jemand eine Idee, wie ich möglichst effizient, die Listenelemente gleichmäßig von allen Threads parallel abarbeiten kann. (Vielleicht mit einer Queue, die vorher jedesmal gefüllt wird, wobei ich da mir nicht sicher bin , wieviel Overhead ich bekomme, durch das Queue Befüllen und Rausfischen dereinzelnen Elemente).

Uff geschafft, vielen Dank schonmal fürs Durchlesen.
Gruß
stevetc
 
Zurück