Что такое блокирующий метод?
Блокирующий метод — это метод, который приостанавливает выполнение вызвавшего его потока до тех пор, пока не будет выполнено определённое условие (завершение операции ввода-вывода, поступление данных, истечение таймаута и т.п.). Управление не возвращается вызывающему коду, пока метод не завершится.
Примеры блокирующих методов:
| Метод | Что ожидает |
|---|---|
ServerSocket.accept() |
Подключение клиента |
InputStream.read() |
Поступление данных |
BlockingQueue.take() |
Появление элемента в очереди |
Future.get() |
Завершение асинхронной задачи |
Thread.join() |
Завершение другого потока |
Lock.lock() |
Освобождение блокировки |
CountDownLatch.await() |
Обнуление счётчика |
Thread.sleep() |
Истечение заданного времени |
Неблокирующие альтернативы (асинхронные методы) могут вернуть управление немедленно, не дожидаясь результата. Например:
Пример
// Блокирующий вызов — поток стоит, пока не придёт ответ
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
// Неблокирующий вызов — возвращает CompletableFuture сразу
CompletableFuture<HttpResponse<String>> future =
httpClient.sendAsync(request, BodyHandlers.ofString());
Связь с Virtual Threads (Java 21+). Виртуальные потоки делают блокирующие вызовы «дешёвыми»: когда виртуальный поток вызывает блокирующий метод, JVM автоматически отсоединяет его от потока-носителя, позволяя последнему выполнять другие виртуальные потоки. Это означает, что простой блокирующий код (socket.read(), queue.take()) при использовании виртуальных потоков по масштабируемости приближается к асинхронному.
Аналогия: блокирующий метод — это ожидание в очереди на почте. Вы стоите (поток заблокирован) и не можете делать ничего другого, пока не подойдёт ваша очередь. Неблокирующий метод — это когда вы берёте талончик с номером и идёте заниматься своими делами, пока вас не вызовут.
На собеседовании могут спросить: «Почему блокирующие вызовы проблематичны?» Ключевой ответ: каждый заблокированный Platform Thread занимает ~1 МБ стека и системные ресурсы, поэтому при тысячах одновременных блокировок ресурсы исчерпываются. Virtual Threads решают эту проблему, потому что блокировка виртуального потока не блокирует ОС-поток.