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

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 секунды

Объект "[защита электронной почты]" просыпается после ожидания в течение 1 секунды

3. Просыпаться, ждать и спать

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

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

Использование notifyAll () вместо того , чтобы уведомить () , если вы хотите , чтобы разбудить все потоки , которые находятся в состоянии ожидания. Аналогично ожидание () метод сам, уведомляет () , и 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.