【发布时间】:2021-02-04 18:05:59
【问题描述】:
下面代码的问题是我必须等待所有三个任务都完成。
如果第一个和第二个任务在 200 毫秒内完成,而第三个任务在 2 秒内完成,那么我将不得不等待 2 秒才能加载接下来的三个 URL。
理想情况下,我会在每个任务完成后立即发送一个新请求,并以某种方式延迟主线程,直到 ArrayList 为空。
简单来说,我希望每个可完成的未来都在一种由旧任务完成触发的循环中运行。
(我经常在 JavaScript 中使用事件这样做)
谁能想到我如何做到这一点?
private static void httpClientExample(){
ArrayList<String> urls = new ArrayList<>(
Arrays.asList(
"https://www.bing.com/",
"https://openjdk.java.net/",
"https://openjdk.java.net/",
"https://google.com/",
"https://github.com/",
"https://stackoverflow.com/"
));
HttpClient httpClient = HttpClient.newHttpClient();
var task1 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create(urls.get(0)))
.build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
var task2 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create(urls.get(1)))
.build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
var task3 = httpClient.sendAsync(HttpRequest.newBuilder()
.uri(URI.create(urls.get(2)))
.build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::uri).thenAccept(System.out::println);
// All tasks have to complete
var all = CompletableFuture.allOf(task1, task2, task3).join();
// Get the next 3 URLs
System.out.println("Main Thread Completed");
}
【问题讨论】:
-
您是否有任何理由要等待所有 3 个请求完成后再继续?如果唯一的要求是最多发出 3 个并行请求,您可以使用最多 3 个线程的
ExecutorService。 -
@dpr 完全没有理由。我只是想确保在主线程退出之前完成所有三个任务。
-
您是指所有 6 个(URL 数量)任务?
-
我更新了我的答案。没有“最多 3 个并行调用”的要求,它变得更简单了。
标签: java java-11 java-http-client