- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了几行代码,它将向我的计算机上运行的服务发送 50 个 HTTP GET 请求。该服务将始终 hibernate 1
秒并返回 HTTP 状态代码 200 和空正文。正如预期的那样,代码运行了大约 50 秒。
为了加快速度,我尝试创建一个具有 4 个线程的 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...
所以我的问题是为什么带有 sleep 调用的代码可以按预期工作,而带有 HTTP 请求的代码却不能?我怎样才能让它按照我预期的方式运行?
最佳答案
从信息中,我可以看出这是最可能的根本原因:
The requests you make are done in parallel but the HTTP server which fulfils these request handles 1 request at a time.
因此,当您开始发出请求时,执行器服务会同时启动请求
,因此您可以同时获得前 4 个请求。
但是HTTP 服务器可以响应请求一次一个,即每次 1 秒后。
现在,当第一个请求完成时,执行程序服务会选择另一个请求并触发它,这种情况会一直持续到最后一个请求。
HTTP 服务器一次阻止 4 个请求,这些请求一个接一个地串行处理。
要获得该理论的概念验证
,您可以使用消息服务(队列),该服务可以同时从 4 个 channel 接收测试。这应该会减少时间。
关于java - 为什么这个线程池不同时执行HTTP请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52917313/
我是一名优秀的程序员,十分优秀!