Рубрики
Без рубрики

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

Быстрый и практический пример разницы между методами sleep() и wait() в Java.

Автор оригинала: baeldung.

1. Обзор

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

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

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

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

С другой стороны, 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 секунды Объект ‘ [email protected] ‘ пробуждается после ожидания в течение 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(); 
    } 
}

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

Ожидание завершения потока… Поток завершен. Сумма из этого потока: 704982704

4. Заключение

Это краткое руководство по семантике wait и sleep в Java.

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

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