Ответ
В Java ожидание ответа или завершения операции можно реализовать несколькими способами, выбор зависит от контекста: многопоточность, асинхронность или тестирование.
Основные подходы:
-
Thread.sleep()— простейшая блокировка потока на указанное время. Не рекомендуется для production-кода, так как поток бесполезно занят.Thread.sleep(1000); // Поток блокируется на 1 секунду -
wait()/notify()— механизм ожидания по условию в рамках синхронизированного блока.synchronized (lockObject) { while (!conditionMet) { lockObject.wait(); // Освобождает монитор и ждет notify() } // Условие выполнено, продолжаем работу } -
FutureиCompletableFuture— для асинхронных вычислений. Методget()блокирует поток до получения результата.CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return longRunningOperation(); }); String result = future.get(); // Блокирующее ожидание -
CountDownLatch,CyclicBarrier,Semaphore— высокоуровневые синхронизаторы изjava.util.concurrentдля координации потоков.CountDownLatch latch = new CountDownLatch(1); // В другом потоке после выполнения задачи: latch.countDown(); // Ожидание в основном потоке: latch.await();
Для тестирования удобно использовать библиотеку Awaitility, которая позволяет декларативно описывать ожидания.
await().atMost(5, SECONDS).until(() -> service.isReady());
Рекомендация: В production-коде предпочтительны асинхронные подходы (CompletableFuture, реактивные стримы) или специализированные синхронизаторы, чтобы избежать бесполезной блокировки потоков.
Ответ 18+ 🔞
А, слушай, про ожидание в Java, да? Ну это ж классика, блядь! Ситуаций — овердохуища: то поток засранец тормозит, то ответ от сервиса как от козла молока. Главное — не тупить и выбрать нормальный способ, а не костылить.
Вот смотри, какие варианты есть, от примитивных до асексуальных, блядь.
Ну, поехали, разбираем эту срань:
-
Thread.sleep()— это как молотком по пальцу, чтоб не дёргался. Самый тупой способ, поток в говно просто лежит и спит указанное время. В продакшене так делать — себя не уважать, ёпта. Только для тестов или отладки, когда мозгов не хватает.Thread.sleep(1000); // Поток вырубается на секунду, как будто ему по башке дали -
wait()/notify()— уже интереснее, как в тюрьме: сидишь в камере (synchronized), пока надзиратель не постучит (notify()). Только не забудь проверку условия в цикле, а то проснёшься, а хуй тебе, а не работа.synchronized (lockObject) { while (!conditionMet) { lockObject.wait(); // Сдал монитор и уснул, ждёшь пинка } // А вот тут уже можно работать, условие выполнилось } -
FutureиCompletableFuture— это когда ты отдал задание какому-нибудь левому потоку-обормоту и ждёшь, пока он не принесёт тебе результат. Методget()— это такой суровый взгляд, после которого поток-исполнитель сразу понимает, что надо пахать, и блокирует всё, пока не сделает.CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return longRunningOperation(); // Какая-то долбаная операция }); String result = future.get(); // Сидишь и тупо ждёшь, как лох -
CountDownLatch,CyclicBarrier— это уже серьёзные пацаны изjava.util.concurrent. Представь, что ты собрал орду потоков и говоришь: «Не двинетесь с места, пока все не прибудут!».CountDownLatch— одноразовый,CyclicBarrier— циклический, как карусель, блядь.CountDownLatch latch = new CountDownLatch(1); // Где-то в другом потоке, после всех дел: latch.countDown(); // Крикнул "Свободен!" // А здесь, в основном, ждёшь: latch.await(); // Стоишь, ушами хлопаешь, пока не услышишь
Для тестов — вообще отдельная песня. Не надо изобретать велосипед, есть же Awaitility. Красота, блядь! Написал условие человеческим языком и пошёл чай пить.
await().atMost(5, SECONDS).until(() -> service.isReady()); // Жди, сука, пока сервис не будет готов, но не больше пяти секунд, а то заебёшь
Итог, ёпта: Если пишешь нормальный код, а не учебную хуйню — забей на Thread.sleep() как на зуд в жопе. Используй CompletableFuture для асинхронности или синхронизаторы для сложной координации. Потоки — дорогие, их жалко, не заставляй их просто так спать, ебать твою в душу!