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 .