Різниця між очікуванням та сном у 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"); } } 

Запуск цього прикладу дасть такий результат:

Нитка «основна» прокидається після сну протягом 1 секунди

Об'єкт "[електронна пошта захищена]" пробуджується після очікування протягом 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 () для керування часом виконання одного потоку і чекати () для багатопотокової синхронізації. Звичайно, є ще багато чого для вивчення - добре зрозумівши основи.

Як завжди, ви можете ознайомитися з прикладами, наведеними в цій статті, на GitHub.