簡體   English   中英

Java 8:如何將for循環轉換為並行運行?

[英]Java 8: How can I convert a for loop to run in parallel?

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

我有一種情況,我必須為10萬用戶請求一個資源,它需要70分鍾才能完成。 我試圖盡可能地清理我的代碼,我只能將它減少4分鍾)。

由於每個請求彼此獨立,我很樂意並行發送請求(可能是10s,100s甚至1000s的塊,每次快速完成)。 我希望我能把時間減少到10分鍾或者接近的時間。 如何計算哪個塊大小可以快速完成工作?

我找到了以下方法,但我不知道該程序是否一次處理所有20個; 或一次5個; 或者一次10個。

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

我知道你的幫助。 我對任何建議或評論都持開放態度!

更新:我能夠使用IntStream,並在28分鍾內完成任務。 但我不確定這是我能做的最好的。

我在Java 8中使用了以下代碼,它完成了工作。 我能夠將批處理作業從28分鍾減少到3:39分鍾。

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

parallel()的標准調用將使用Common Fork Join Pool為您的機器可用的每個核心減去一個核心創建一個線程。

如果您想自己指定並行性,您將有不同的可能性:

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

這個實現只是為了給你一個想法的示例。

根據您的情況,您可以使用fork / join框架或創建執行程序服務池線程。

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

並使用fork / join框架

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

我寫過一篇關於此的短文。 它包含允許您控制池大小的簡單工具:

https://gt-dev.blogspot.com/2016/07/java-8-threads-parallel-stream-how-to.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM