2016-04-28 10 views
1

Hier ist mein Problem: Ich habe eine Bevölkerung von sagen wir 200 Personen. Ziel ist es, diese Bevölkerung zu optimieren. Jede Person hat mehrere Parameter und diese Parameter werden verwendet, um dieser Person einen Wert (Qualitätsstufe) zuzuweisen. Die Berechnung dieses Wertes kann für jede Person getrennt erfolgen, dauert jedoch jeweils einige Sekunden. Mein Laptop hat 4 Prozessoren und ich habe festgestellt, dass die Berechnungen 3 mal so schnell durchgeführt werden können, indem mehrere Threads verwendet werden (über Runnable, 1 Haupt-Thread, 7 Threads für Einzelpersonen, 7 Personen werden gleichzeitig verarbeitet, dann die nächsten 7). Ich habe jedoch keine Kenntnisse über Threads und meine Implementierung ist fehlerhaft. Höchstwahrscheinlich wird das Programm beendet, aber es gibt auch eine Chance, dass es einfriert (was mich 1 Stunde der durchgeführten Berechnungen kosten kann). Je mehr andere Programme ich ausführe, desto höher ist die Wahrscheinlichkeit eines Fehlers. Also, wie macht man das richtig? Danke im Voraus.Java parallele Berechnung/threading

public class EntropyParralel 
{ 
    private static final int maxThreads = 7; 
    static final int populationSize = 200; 
    static Individual[] population; 
    static Thread[] threads; 
    static int finishedThreads; 
    static int startedThreads; 

    static class Individual implements Runnable 
    { 
     // ... 

     public void run() 
     { 
      eval(); 
      finishedThreads += 1; 
     } 
    } 

    public static void newEntropy() 
    { 
     // ... 

     threads = new Thread[ population.length ]; 
     for (int i = 0; i < threads.length; i++) 
      threads[i] = new Thread(population[i]); 
     startedThreads = 0; finishedThreads = 0; 
     while(finishedThreads < threads.length) 
     { 
      if (startedThreads - finishedThreads < maxThreads && startedThreads < threads.length) 
      { 
       threads[startedThreads].start(); 
       startedThreads += 1; 
      } 
      try 
      { 
       Thread.sleep(1); 
      } 
      catch(Exception e){} 
     } 
     sortPopulation(); 

     // ... 
    } 
} 

edit:

kein anständiges ExecutorService Beispiel in Bezug auf einfache Feldberechnung gefunden werden. Also habe ich weiterhin Runnable und Thread verwendet. Diesmal zählen fertige und neue Threads über thread.getState(). Gleich (Thread.State.TERMINATED) in jedem Haupt-Loop-Frame. Und es scheint richtig zu funktionieren. Hatte einen Test über 10.000 Iterationen bei einem kleineren Problem und es nicht eingefroren.

public class EntropyParallel 
{ 
    private static final int maxThreads = 7; 
    static final int populationSize = 200; 

    static class Individual implements Runnable 
    { 
     // ... 

     public void run() 
     { 
      eval(); 
     } 
    } 

    public static void newEntropy() 
    { 
     // ... 

     Thread[] threads = new Thread[ population.length ]; 
     for (int i = 0; i < threads.length; i++) 
      threads[i] = new Thread(population[i]); 
     while(true) 
     { 
      int finishedThreads = 0; int availableThreads = 0; 
      for (int i = 0; i < threads.length; i++) 
      { 
       if (threads[i].getState().equals(Thread.State.TERMINATED)) 
        finishedThreads += 1; 
       else if (threads[i].getState().equals(Thread.State.NEW)) 
        availableThreads += 1; 
      } 
      if (finishedThreads == threads.length) 
       break; 
      for (int i = 0; i < threads.length; i++) 
      { 
       if (threads.length - finishedThreads - availableThreads >= maxThreads || availableThreads == 0) 
        break; 
       if (threads[i].getState().equals(Thread.State.NEW)) 
       { 
        threads[i].start(); 
        availableThreads -= 1; 
       } 
      } 
      try 
      { 
       Thread.sleep(1); 
      } 
      catch(Exception e){} 
     } 
     sortPopulation(); 

     // ... 
    } 
} 
+2

Siehe Executors. und ExecutorService – ControlAltDel

Antwort

0

Sie müssen nicht alle Threads manuell erstellen und starten. Sehen Sie sich java.util.concurrent.CompletionService an. Sie können kleine Codeabschnitte erstellen, die nur die Berechnung durchführen und dann an diesen CompletionService übergeben, dann werden alle Ihre Aufgaben ausgeführt und Sie können sie nach Abschluss betrachten.

Ich schlage vor, Sie sehen sich ExecutorCompletionService und Executors-Klasse. Sie werden Ihnen helfen