Параллелизм Java предоставляет два метода, sleep() и wait() для управления потоком выполнения потоков. Хотя оба метода кажутся схожими по назначению, они играют разные роли.
В этом уроке Java мы изучим разницу между методами sleep() и wait(). Мы также узнаем, когда какой метод использовать и какой эффект они приносят в параллелизме Java.
1. Метод Java Thread.sleep()
Thread.sleep() — это статический метод, который временно приостанавливает выполнение текущего потока на указанный период времени. В течение этого времени поток остается в состоянии TIMED_WAITING.
- Метод sleep() лучше всего использовать в сценариях, когда мы хотим отложить выполнение потока на определенный период времени, ожидая ресурс.
- Довольно часто метод sleep() используется для имитации длительной операции или временного интервала между задачами во время модульного тестирования.
import java.time.LocalDateTime;public class SleepExample {public static void main(String[] args) {LocalDateTime start = LocalDateTime.now();System.out.println("Thread started at: " + start);try {Thread.sleep(2000); // Sleep for 2 seconds} catch(InterruptedException e) {e.printStackTrace();}LocalDateTime end = LocalDateTime.now();System.out.println("Thread resumed after sleep at: " + end);}}
Вывод программы:
Thread started at: 2022-05-12T09:30:45.123456Thread resumed after sleep at: 2022-05-12T09:30:47.125789
В этом примере поток начался в 2022-05-12T09:30:45.123456 и возобновился после сна в 2022-05-12T09:30:47.125789. Фактические временные метки будут зависеть от текущего времени выполнения программы.
Поскольку sleep() является статическим методом, это означает, что он всегда влияет на текущий поток(тот, который выполняет метод sleep).
Распространенной ошибкой является вызов t.sleep(), где t — другой поток; даже в этом случае спать будет текущий поток, а не поток t.
2. Метод Java Object.wait()
Метод wait() — это нестатический метод, определенный в классе Object и используемый для межпотоковой коммуникации и синхронизации. Когда поток вызывает wait() для объекта, он снимает блокировку с объекта и переходит в состояние WAITING, пока другой поток не уведомит его с помощью методов notify() или notifyAll().
Мы обычно используем метод wait() для решения шаблона производитель-потребитель или других сценариев синхронизации.
import java.time.LocalDateTime;public class WaitExample {public static void main(String[] args) {Object lock = new Object();LocalDateTime start = LocalDateTime.now();System.out.println("Thread started at: " + start);Thread waitingThread = new Thread(() -> {synchronized(lock) {try {System.out.println("Waiting for notification at: " + LocalDateTime.now());lock.wait(); // Wait until notifiedSystem.out.println("Notification received at: " + LocalDateTime.now());} catch(InterruptedException e) {e.printStackTrace();}}});Thread notifyingThread = new Thread(() -> {synchronized(lock) {try {Thread.sleep(2000); // Simulate some processing timelock.notify(); // Notify waiting threadSystem.out.println("Notification sent at: " + LocalDateTime.now());} catch(InterruptedException e) {e.printStackTrace();}}});waitingThread.start();notifyingThread.start();// Wait for threads to finishtry {waitingThread.join();notifyingThread.join();} catch(InterruptedException e) {e.printStackTrace();}LocalDateTime end = LocalDateTime.now();System.out.println("Thread finished at: " + end);}}
В этом примере:
- Программа запускается и печатает метку времени запуска.
- Ожидающий поток запускается и печатает временную метку ожидания.
- Уведомляющий поток отправляет уведомление через 2 секунды и печатает временную метку уведомления.
- Ожидающий поток получает уведомление и печатает полученную временную метку.
- Программа завершается и печатает временную метку завершения.
Фактические временные метки будут зависеть от текущего времени.
Вывод программы:
Thread started at: 2022-05-12T09:30:45.123456Waiting for notification at: 2022-05-12T09:30:45.123456Notification sent at: 2022-05-12T09:30:47.125789Notification received at: 2022-05-12T09:30:47.125789Thread finished at: 2022-05-12T09:30:47.125789
Подробнее: Работа с wait() и notify()
3. Разница между методами wait() и sleep()
Главное отличие в том, что wait() снимает блокировку или монитор, а sleep() не снимает блокировку во время ожидания. Wait() используется для межпоточной коммуникации, а sleep() используется для введения паузы при выполнении, в общем случае.
В следующей таблице приведены основные различия между методами wait() и sleep():
Особенность | ждать() | спать() |
---|---|---|
Метод Расположение | Определено в классе Object | Определено в классе Thread |
Использование | Используется для межпоточной коммуникации и синхронизации. | Используется для приостановки выполнения потока. |
Снятие блокировки | Снимает блокировку с объекта, на котором ведется ожидание. | Не снимает блокировку |
Зависимость объекта | Вызывается для объекта внутри синхронизированного блока | Вызывается непосредственно на объекте Thread |
Прерывание | Выдает InterruptedException при прерывании | Также выдает InterruptedException при прерывании |
Уведомление | Для возобновления выполнения требуется notify() или notifyAll() | Неприменимо, поток автоматически возобновляется после сна |
Ассоциированное государство | Переводит поток в состояние WAITING или TIMED_WAITING | Переводит поток в состояние TIMED_WAITING |
Указание времени | Продолжительность не указана | Продолжительность времени указана в миллисекундах |
Подробнее: Разница между yield() и join()
4. Резюме
Давайте кратко классифицируем все вышеперечисленные пункты, чтобы их было легче запомнить.
4.1. Метод вызван
- wait() – вызов объекта; текущий поток должен синхронизироваться с объектом блокировки.
- sleep() – вызов потока; всегда текущий выполняющийся поток.
4.2 Синхронизированный
- wait() – при синхронизации несколько потоков обращаются к одному и тому же объекту по одному.
- sleep() – при синхронизации нескольких потоков ожидается переход в спящий режим спящего потока.
4.3 Продолжительность блокировки
- wait() – снять блокировку, чтобы другие объекты получили возможность выполниться.
- sleep() – удерживать блокировку не менее t раз, если указано время ожидания или кто-то прервал ее.
4.4. состояние пробуждения
- wait() – пока не вызовется notify(), notifyAll() из объекта
- sleep() – по крайней мере до истечения времени или вызова interrupt().
4.5 Использование
- sleep() – для синхронизации времени
- wait() – для многопоточной синхронизации.
Надеюсь, приведенная выше информация добавит ценности в вашу базу знаний.