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

私は100kユーザーのリソースを要求しなければならない状況があり、終了するまでに70分かかります。私は可能な限りコードを整理しようとしましたが、私はそれを4分だけ減らすことができました。Java 8:forループを並列で実行するにはどうすればよいですか?

各リクエストは互いに独立しているので、私はリクエストを並行して送信したいと思っています(10秒、100秒、または1000秒のチャンクですばやく完了します)。私は10分かそれ以上の時間を短縮できると思っています。どのチャンクサイズでジョブをすばやく完了させるかを計算するにはどうすればよいですか?

私は次の方法を見つけましたが、プログラムが20個ずつ同時に処理するかどうかはわかりません。または一度に5つ。または10ずつ。

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

私はあなたの助けをappericiate。私はどんな提案や評論家にも開いています!

更新:私はIntStreamを使用することができ、タスクは28分で終了しました。しかし、私はこれが私が行くことができる最高ののか分からない。

+0

*私は、任意の提案や批評家に開く!! * - 私はあなたが 'IntStream'方法は、一度パソコン内のコアの数に等しい要求の数を処理するサイレント批評家に –

+0

を得ていると思います。速度を上げたい場合は、** Async ** Httpクライアントを使用してください。したがって、応答を受け取るまでブロッキングは発生しません。 –

+0

@ SkaryWombat Lol。同感です! – WowBow

答えて

4

私は、Java 8で次のコードを使用し、それが仕事をした:それはあなたがプールのサイズを制御することを可能にするシンプルなツールが含まれています。バッチジョブを28分から3:39分に短縮することができました。

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

フォーク/ジョイン・フレームワークで作業したり、スレッドの実行プログラム・サービス・プールを作成したりすることができます。 parallel()

 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"); 

とフォークを使って/参加する枠組み

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

彼のボトルネックは並列処理ではありません。リクエストをブロックしています。したがって、これは何の役にも立たないでしょう。 –

+0

私は彼がパラレルマナーでリクエストを分割する方法について質問していると思った。 –

+0

@ImeshaSudasinghaリクエストをブロックすることはどういう意味ですか?リクエストを並行して分割するよう依頼しました。 – WowBow

1

標準呼び出しがCommon Fork Join Poolを使用して、あなたのマシンが利用できる持っている各コアのスレッドを作成マイナス1つのコアます。

自分で並列処理を指定したい場合、あなたは異なる可能性があります:

  1. 変更共通プールの平行度を:System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "20")
  2. 自身のプールを使用します

を例:

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); 
      }); 
})); 

この実装はjusですあなたにアイデアを与えるために試してみてください。

関連する問題