Concurrency Средний

Параллельные HTTP-запросы с виртуальными потоками

Одновременная загрузка множества URL с помощью виртуальных потоков и HttpClient.

✕ 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.

📖

Простой код

Пишите простой блокирующий код.

Высокая пропускная способность

Тысячи одновременных запросов с минимальными ресурсами.

Старый подход
Thread Pool + URLConnection
Современный подход
Виртуальные потоки + HttpClient
Начиная с JDK
21
Сложность
Средний
Параллельные HTTP-запросы с виртуальными потоками
Доступно

Широко доступно с JDK 21 LTS (сент. 2023)

Виртуальные потоки позволяют практично создавать по одному потоку на каждый HTTP-запрос. В сочетании с HttpClient это заменяет сложные асинхронные колбэк-паттерны простым блокирующим кодом, который хорошо масштабируется.