Перейти к основному содержимому

Разница между ожиданием и сном в Java

· 3 мин. чтения

1. Обзор

В этой короткой статье мы рассмотрим стандартные методы sleep() и wait() в базовой версии Java и поймем различия и сходства между ними.

2. Общие различия между ожиданием и сном

Проще говоря, wait() — это метод экземпляра, который используется для синхронизации потоков.

Его можно вызвать для любого объекта, так как он определен прямо в java.lang.Object, но его можно вызвать только из синхронизированного блока . Он освобождает блокировку объекта, чтобы другой поток мог подключиться и получить блокировку.

С другой стороны, Thread.sleep() — это статический метод, который можно вызывать из любого контекста. Thread.sleep() приостанавливает текущий поток и не снимает блокировки. ``

Вот очень упрощенный начальный взгляд на эти два основных API в действии:

private static Object LOCK = new Object();

private static void sleepWaitExamples()
throws InterruptedException {

Thread.sleep(1000);
System.out.println(
"Thread '" + Thread.currentThread().getName() +
"' is woken after sleeping for 1 second");

synchronized (LOCK) {
LOCK.wait(1000);
System.out.println("Object '" + LOCK + "' is woken after" +
" waiting for 1 second");
}
}

Выполнение этого примера приведет к следующему выводу:

Поток 'main' пробуждается после ожидания в течение 1 секунды

. Объект ' java.lang.Object@31befd9f ' пробуждается после ожидания в течение 1 секунды.

3. Пробуждение Подождите и засните

Когда мы используем метод sleep() , поток запускается через указанный интервал времени, если только он не был прерван.

Для wait() процесс пробуждения немного сложнее. Мы можем разбудить поток, вызвав методы notify( ) или notifyAll() на ожидаемом мониторе.

Используйте notifyAll() вместо notify( ) , если вы хотите разбудить все потоки, находящиеся в состоянии ожидания. Аналогично самому методу wait() , методы notify( ) и notifyAll() должны вызываться из синхронизированного контекста.

Например, вот как вы можете ждать :

synchronized (b) {
while (b.sum == 0) {
System.out.println("Waiting for ThreadB to complete...");
b.wait();
}

System.out.println("ThreadB has completed. " +
"Sum from that thread is: " + b.sum);
}

И затем, вот как другой поток может разбудить ожидающий поток, вызвав notify() на мониторе :

int sum;

@Override
public void run() {
synchronized (this) {
int i = 0;
while (i < 100000) {
sum += i;
i++;
}
notify();
}
}

Выполнение этого примера приведет к следующему выводу:

Ожидание завершения ThreadB…

ThreadB завершен. Сумма из этого потока: 704982704

4. Вывод

Это краткое введение в семантику ожидания и сна в Java.

В общем, мы должны использовать sleep() для управления временем выполнения одного потока и wait() для многопоточной синхронизации. Естественно, есть еще много чего для изучения — после того, как вы хорошо разберетесь с основами.

Как всегда, вы можете ознакомиться с примерами, представленными в этой статье , на GitHub .