1
for (int i=0; i<100000; i++) { 
    // REST API request. 
restTemplate.exchange(url, HttpMethod.GET, request, String.class); 
} 

Ich habe eine Situation, wo ich eine Ressource für 100k Benutzer anfordern muss und es 70 Minuten dauert, um zu beenden. Ich habe versucht, meinen Code so gut wie möglich aufzuräumen und konnte ihn nur um 4 Minuten reduzieren).Java 8: Wie kann ich eine for-Schleife konvertieren, um parallel zu laufen?

Da jede Anfrage unabhängig voneinander ist, würde ich gerne Anfragen parallel senden (kann in 10s, 100s oder sogar 1000s von Chunks sein, die alle schnell fertig sind). Ich hoffe, dass ich die Zeit auf 10 Minuten oder etwas knappes reduzieren kann. Wie berechne ich, welche Chunk-Größe den Job schnell erledigt?

Ich habe den folgenden Weg gefunden, aber ich kann nicht sagen, ob das Programm alle 20 auf einmal verarbeitet; oder 5 gleichzeitig; oder 10 auf einmal.

IntStream.range(0,20).parallel().forEach(i->{ 
    ... do something here 
}); 

Ich apperiate Ihre Hilfe. Ich bin offen für irgendwelche Vorschläge oder Kritiker !!

UPDATE: Ich konnte IntStream verwenden und die Aufgabe in 28 Minuten abgeschlossen. Aber ich bin mir nicht sicher, dass dies das Beste ist, was ich erreichen kann.

+0

* ich offen für alle Anregungen oder Kritik !! * - Ich denke, man eine Reihe von Anfragen stillen Kritiker –

+0

Die 'IntStream' Methode verarbeiten zu einer Zeit, die gleich der Anzahl der Kerne in Ihrem Computer bekommen. Wenn Sie mehr Geschwindigkeit erreichen möchten, verwenden Sie ** Async ** Http-Clients. Daher erfolgt keine Blockierung, bis Sie die Antwort erhalten. –

+0

@ScaryWombat Lol. Ich wiederhole das! – WowBow

Antwort

4

ich den folgenden Code in Java 8 verwendet, und es hat die Arbeit. Ich konnte den Stapeljob von 28 Minuten auf 3:39 Minuten reduzieren.

IntStream.range(0, 100000).parallel().forEach(i->{ 
    restTemplate.exchange(url, HttpMethod.GET, request, String.class); 
} 
}); 
0

Für Ihre Situation können Sie mit Fork/Join Framework arbeiten oder Executor Service-Pool von Threads machen.

 ExecutorService service = null; 
    try { 

     service = Executors.newFixedThreadPool(8); 
     service.submit(() -> { 

      //do your task 
     }); 
    } catch (Exception e) { 
    } finally { 
     if (service != null) { 
      service.shutdown(); 
     } 

    } 
    service.awaitTermination(1, TimeUnit.MINUTES); 
    if(service.isTerminated()) 
     System.out.println("All threads have been finished"); 
    else 
     System.out.println("At least one thread running"); 

Und mit Gabel/join Rahmen

class RequestHandler extends RecursiveAction { 

    int start; 
    int end; 

    public RequestHandler(int start, int end) { 
     this.start = start; 
     this.end = end; 
    } 

    @Override 
    protected void compute() { 
     if (end - start <= 10) { 

      //REST Request 
     } else { 

      int middle = start + (end - start)/2; 
      invokeAll(new RequestHandler(start, middle), new RequestHandler(middle, end)); 
     } 

    } 

} 

Public class MainClass{ 
    public void main(String[] args){ 

     ForkJoinTask<?> task = new RequestHandler(0, 100000); 
     ForkJoinPool pool = new ForkJoinPool(); 
     pool.invoke(task); 
    } 
} 
+0

Sein Flaschenhals ist nicht in Parallelverarbeitung. Es blockiert Anfragen. Daher wird dies nichts nützen. –

+0

Ich dachte, er fragt, wie man die Anfragen parallel teilen kann maner –

+0

@ImeshaSudasingha Was meinst du mit Blockieren von Anfragen? Ich habe darum gebeten, Anfragen parallel zu teilen. – WowBow

1

Der Standard-Aufruf parallel() einen Thread für jeden Kern Ihrer Maschine minus einem Kern zur Verfügung hat erstellen, ein Common Fork Join Pool verwenden.

Wenn Sie die Parallelität auf Ihrem eigenen angeben möchten, müssen Sie verschiedene Möglichkeiten:

  1. Ändern Sie die Parallelität des gemeinsamen Pool: System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "20")
  2. Verwenden Sie einen eigenen Pool:

Beispiel:

int allRequestsCount = 20; 
int parallelism = 4; // Vary on your own 

ForkJoinPool forkJoinPool = new ForkJoinPool(parallelism); 
IntStream.range(0, parallelism).forEach(i -> forkJoinPool.submit(() -> { 
    int chunkSize = allRequestsCount/parallelism; 
    IntStream.range(i * chunkSize, i * chunkSize + chunkSize) 
      .forEach(num -> { 

      // Simulate long running operation 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

      System.out.println(Thread.currentThread().getName() + ": " + num); 
      }); 
})); 

Diese Implementierung ist jus Beispielhaft, um Ihnen eine Idee zu geben.

Verwandte Themen