Я написал несколько строк кода, которые будут отправлять 50 HTTP-запросов GET службе, работающей на моей машине.Служба всегда будет sleep 1
секунду и вернет код состояния HTTP 200 с пустым телом.Как и ожидалось, код выполняется около 50 секунд.
Чтобы немного ускорить процесс, я попытался создать ExecutorService
с четырьмя потоками, чтобы всегда мог отправлять 4 запроса одновременно на мой сервис.Я ожидал, что код будет выполняться в течение 13 секунд.
final List<String> urls = new ArrayList<>();
for (int i = 0; i < 50; i++)
urls.add("http://localhost:5000/test/" + i);
final RestTemplate restTemplate = new RestTemplate();
final List<Callable<String>> tasks = urls
.stream()
.map(u -> (Callable<String>) () -> {
System.out.println(LocalDateTime.now() + " - " + Thread.currentThread().getName() + ": " + u);
return restTemplate.getForObject(u, String.class);
}).collect(Collectors.toList());
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final long start = System.currentTimeMillis();
try {
final List<Future<String>> futures = executorService.invokeAll(tasks);
final List<String> results = futures.stream().map(f -> {
try {
return f.get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(e);
}
}).collect(Collectors.toList());
System.out.println(results);
} finally {
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
}
final long elapsed = System.currentTimeMillis() - start;
System.out.println("Took " + elapsed + " ms...");
Но - если вы посмотрите на секунды вывода отладочной информации - кажется, что первые 4 запроса выполняются одновременно, но все остальные запросы выполняются одинза другим:
2018-10-21T17:42:16.160 - pool-1-thread-3: http://localhost:5000/test/2
2018-10-21T17:42:16.160 - pool-1-thread-1: http://localhost:5000/test/0
2018-10-21T17:42:16.160 - pool-1-thread-2: http://localhost:5000/test/1
2018-10-21T17:42:16.159 - pool-1-thread-4: http://localhost:5000/test/3
2018-10-21T17:42:17.233 - pool-1-thread-3: http://localhost:5000/test/4
2018-10-21T17:42:18.232 - pool-1-thread-2: http://localhost:5000/test/5
2018-10-21T17:42:19.237 - pool-1-thread-4: http://localhost:5000/test/6
2018-10-21T17:42:20.241 - pool-1-thread-1: http://localhost:5000/test/7
...
Took 50310 ms...
Поэтому для целей отладки я изменил HTTP-запрос на sleep
вызов:
// return restTemplate.getForObject(u, String.class);
TimeUnit.SECONDS.sleep(1);
return "";
И теперь код работает, как и ожидалось:
...
Took 13068 ms...
Итак, мой вопрос: почему код с вызовом в спящем режиме работает должным образом, а код с запросом HTTP - нет?И как мне заставить его вести себя так, как я ожидал?