2016-04-21 2 views
1

Ich habe die folgenden Code-SchnipselWie verschachtelte Schleifen in Java 7 (Android) parallelisieren

String result; 
     for (int s1 = 0; s1 < 10; s1++) 
      for (int s2 = 0; s2 < 100; s2++) 
       for (int s3 = 0; s3 < 10; s3++) 
        for (int s4 = 0; s4 < 100; s4++) 
        { 
         result = doSomething(s1, s2, s3, s4); 
         if (result != null) 
          addResult(result); //adds results to an ArrayList of strings 
        } 

Wie kann ich diesen Code parallelisieren, um es schneller zu machen? Ich habe ähnliche Beiträge hier parallel zu einer einzelnen Schleife gesehen, aber ich möchte diese ganze Sache gleichmäßig parallelisieren, um es anständig auf einem Android-Gerät laufen zu lassen.

+0

3 verschachtelte innere Schleifen ?? Code-stink für sicher – redFIVE

+0

Ich bezweifle, es gibt einen viel schnelleren Weg, es zu tun.Ich wiederhole einfach eine Million Male.Ich sehe nichts, was kann " Vielleicht könnten Sie zwei Schleifen schreiben mit der ersten" s1 = 0; s1 <5 "und zweiten" s1 = 5; s1 <10 ", und führen Sie sie aus gleichzeitig, aber es scheint unnötig komplex.Ich habe keine Ahnung, thoug h. Ich spiele nur mit Gedanken. Vielleicht hätte ich diesen Kommentar gar nicht schreiben sollen. – Gendarme

+1

Es hängt davon ab, was doSomething und addResult tun. Wenn doSomething keine Ergebnisse früherer Schleifen benötigt, können Sie N-Threads starten und jede von ihnen eine Teilmenge der äußersten Schleife ausführen lassen. (Ich gehe davon aus, dass addResult etwas zu einer Liste hinzufügt, wo Sie die Listen im letzten Schritt zusammenführen können). –

Antwort

1

Sie könnten eine AsyncTask verwenden jeder der s1 Ausführungen parallelisieren, zB:

for (int s1 = 0; s1 < 10; s1++) 
{ 
    new AsyncTask<Integer, Object, ArrayList<String>>() 
    { 
     @Override 
     protected ArrayList<String> doInBackground(Integer... params) 
     { 
      ArrayList<String> results = new ArrayList<>(); 
      for (int s2 = 0; s2 < 100; s2++) 
      { 
       for (int s3 = 0; s3 < 10; s3++) 
       { 
        for (int s4 = 0; s4 < 100; s4++) 
        { 
         results.add(doSomething(params[0], s2, s3, s4)); 
        } 
       } 
      } 
      return results; 
     } 

     @Override 
     protected void onPostExecute(ArrayList<String> results) 
     { 
      for(String result : results) { 
       if (result != null) 
        addResult(result); 
      } 
     } 
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, s1); 
}; 

Beachten Sie, dass dies setzt voraus, dass die Reihenfolge der addResult Anrufe sind nicht wichtig, und natürlich, dass doSomething Anrufe nicht stören einander durch Ändern eines gemeinsamen Status. Wenn die Reihenfolge der addResult Aufrufe von Bedeutung sind, können Sie dies lösen, indem Sie ein Array aller Ergebnisse erstellen und warten, bis alle fertig sind (indem Sie einen Zähler erstellen und warten, bis alle 10 Tasks abgeschlossen sind und das Array verarbeiten) der Ergebnisse danach in der Reihenfolge

+3

Die Anzahl der hier erstellten Threads ist zu viel für ein Android-Gerät. Dies wird tatsächlich zu einer langsameren Leistung führen, glaube ich, aber zumindest ist es eine Lösung, die ich versuchen muss. Btw die oben genannten asynctasks werden nicht parallel ausgeführt, außer Sie executeOnExecutor angeben – ThanosFisherman

+2

Hervorhebung ThanosF Punkt, die AsyncTask docs sagen, "beginnend mit HONEYCOMB, Aufgaben werden auf einem einzigen Thread ausgeführt, um häufige Anwendungsfehler durch parallele Ausführung zu vermeiden." Der Teil, den sie nicht sagen, ist, dass AsyncTask-Threads mit einer niedrigeren Priorität festgelegt sind, daher wird die Verwendung für leistungskritischen Code nicht empfohlen. Es gibt viel bessere Ansätze in den Klassen java.util.concurrent. – fadden

+0

Gut zu wissen über executeOnExecutor und die Änderungen an AsyncTask, Antwort wurde aktualisiert. Die Antwort ist als Ausgangspunkt gedacht, wie man AsyncTask anstatt einer optimalen Lösung nutzen kann, je nachdem, was "doSomething" macht, sind 10 zu viele Aufgaben oder zu wenig (z. B. wenn "doSomething" 'waren eine Netzwerkanforderung), aber dies kann leicht geändert werden, indem die Schleife in Abschnitte aufgeteilt wird. In der Tat, wenn dies häufig der Fall ist oder der Aufwand für die Erstellung einer Aufgabe relevant ist, ist die Erstellung mehrerer langlebiger Themen möglicherweise besser geeignet. –