问题描述
在下面的示例中,我创建了一个Java 11 httpClient,然后创建了多个并发的HttpRequest。
- 这是不好的做法吗?
- 每个HttpRequest都有自己的HttpClient吗?
- HttpClient可以拥有的HttpRequest数量上限吗?
private static void httpClientExample(){
HttpClient httpClient = HttpClient.newHttpClient();
System.out.println("TP1");
var task1 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create("https://www.bing.com/"))
.build(),HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
var task2 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create("https://openjdk.java.net/"))
.build(),HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
var task3 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create("https://www.google.co.uk/"))
.build(),HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
System.out.println("Requests Sent");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printstacktrace();
}
System.out.println("Main Thread Completed");
}
解决方法
API docs of HttpClient
中未明确记录。但是可以预期的是,HttpClient被设计为可以处理多个请求。从某种意义上说,这暗示着Introduction to the Java HTTP Client:
一旦构建,便可以使用HttpClient发送多个请求。
现在,您的问题可能是关于管理客户端的并发性。与其使用相同的HttpClient
实例,不如使用它所执行的服务,这是可以自定义的(请参见here):
ExecutorService executorService = Executors.newFixedThreadPool(10);
HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
... //more config
.build();
这样,您可以管理客户端用于运行异步请求的线程池。
换句话说:
这是不好的做法吗?
否
每个HttpRequest都应该有自己的HttpClient吗?
否
HttpClient可以拥有的HttpRequest数量上限吗?
您将必须测试应用程序的最佳并发设置,然后使用相应配置的执行程序服务。
,我要说的是线程的数量而不是对象的数量,因为每个客户端可以通过执行器的线程池使用多个线程,无论是显式声明的还是默认的。因此,真正的问题归结为我们应该使用多少个线程? 这将取决于使用同步请求还是异步请求。
- 使用
send
时,我们从池中使用的线程越多,我们将能够并行发出更多的请求,直到操作系统启动threashing为止,即增加活动的数量。线程实际上减少了完成的工作量。 - 在您的示例中使用
sendAsync
时,事情变得很有趣,因为它是一种非阻塞方法,这意味着同一线程可以在等待处理响应的同时发出多个请求。在这种情况下,我建议执行器池中的线程数应等于处理器核心的数量。