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

У меня возникла ситуация, когда я должен запросить ресурс для пользователей 100 тыс., И это займет 70 минут. Я старался максимально очистить свой код, и я смог уменьшить его только на 4 минуты).Java 8: Как преобразовать цикл for для параллельной работы?

Поскольку каждый запрос не зависит друг от друга, я хотел бы отправлять запросы параллельно (может быть в 10, 100 или даже 1000 кусков, каждый из которых быстро заканчивается). Я надеюсь, что смогу сократить время до 10 минут или что-то близкое. Как рассчитать, какой размер куска быстро выполнит работу?

Я нашел следующий способ, но не могу определить, обрабатывает ли программа все 20 одновременно; или 5 за раз; или 10 за раз.

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

Я предлагаю вам помощь. Я открыт для любых предложений или критиков!

UPDATE: Я смог использовать IntStream, и задача была завершена за 28 минут. Но я не уверен, что это лучшее, что я мог бы сделать.

+0

* Я открыт для любых предложений и критики !! * - Я думаю, вы получаете молчащие критики –

+0

Параметр 'метод IntStream' будет обрабатывать несколько запросов, равное количеству ядер в вашем компьютере одновременно. Если вы хотите достичь большей скорости, используйте ** Async ** Http-клиенты. Поэтому блокировка не происходит, пока вы не получите ответ. –

+0

@ScaryWombat Lol. Во-вторых, это! – WowBow

ответ

4

Я использовал следующий код в Java 8, и он сделал работу. Мне удалось сократить пакетное задание с 28 минут до 3:39 минут.

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

Для вашей ситуации вы можете работать с картой 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"); 

И с помощью вилки/нарисуйте рамки

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

Стандартный вызов 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); 
      }); 
})); 

Эта реализация является jus t, чтобы дать вам представление.