Concurrency 中级

使用虚拟线程进行并发 HTTP 请求

使用虚拟线程和 HttpClient 并发获取多个 URL。

✕ Java 8
ExecutorService pool =
    Executors.newFixedThreadPool(10);
List<Future<String>> futures =
    urls.stream()
    .map(u -> pool.submit(
        () -> fetchUrl(u)))
    .toList();
// manual shutdown, blocking get()
✓ Java 21+
try (var exec = Executors
    .newVirtualThreadPerTaskExecutor()) {
    var results = urls.stream()
        .map(u -> exec.submit(
            () -> client.send(req(u),
                ofString()).body()))
        .toList().stream()
        .map(Future::join).toList();
}
发现此代码有问题? 告诉我们。
♾️

每个请求一个线程

无需调整池大小——每个 URL 一个虚拟线程。

🔒

简单的错误处理

每个任务在自己的线程中处理错误。

📏

简洁代码

现代 HttpClient 与虚拟线程的语义清晰。

旧方式
线程池 + URLConnection
现代方式
虚拟线程 + HttpClient
自 JDK
21
难度
中级
使用虚拟线程进行并发 HTTP 请求
可用

自 JDK 21 LTS 起广泛可用(2023 年 9 月)

虚拟线程使每个 HTTP 请求使用一个线程变得切实可行。每个虚拟线程在等待 I/O 时会挂载,不会阻塞平台线程。

分享 𝕏 🦋 in