Параллельные 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
Сложность
Средний
Поддержка JDK
Параллельные HTTP-запросы с виртуальными потоками
Доступно
Широко доступно с JDK 21 LTS (сент. 2023)
Как это работает
Виртуальные потоки позволяют практично создавать по одному потоку на каждый HTTP-запрос. В сочетании с HttpClient это заменяет сложные асинхронные колбэк-паттерны простым блокирующим кодом, который хорошо масштабируется.
Связанная документация
Доказательство