пример блокировки ожидания
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
try {
waitDemo.doWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(200); // 此行本身没有意义,是为了确保 wait() 先执行再执行 notify()
waitDemo.doNotify();
}
/**
* 执行 wait()
*/
private void doWait() throws InterruptedException {
synchronized (locker) {
System.out.println("wait start.");
locker.wait();
System.out.println("wait end.");
}
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}
Результат выполнения вышеуказанной программы:
wait start.
notify start.
notify end.
wait end.
Разбор кода
Как видно из кода выше, мы даемwait()
иnotify()
Два метода имеют одинаковую блокировку (locker), но после вызоваwait()
после методаlocker
Замок выделяется, поэтому программа может выполняться нормальноnotify()
Код , так как это один и тот же замок, если блокировку не снять, то она не будет выполненаnotify()
кода, это также может быть подтверждено распечатанными результатами (порядок вывода результатов), поэтомуВ связи с вышеуказанной ситуациейwait()
Метод заключается в том, чтобы снять блокировку.
пример блокировки сна
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
synchronized (locker) {
try {
System.out.println("sleep start.");
Thread.sleep(1000);
System.out.println("sleep end.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(200);
waitDemo.doNotify();
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}
Результат выполнения вышеуказанной программы:
sleep start.
sleep end.
notify start.
notify end.
Разбор кода
Как видно из кода вышеsleep(1000)
После выполнения метода (номер строки: 11) вызовитеnotify()
Метод не получает блокировку шкафчика, как видно из приведенных выше результатов выполнения, а после выполненияsleep(1000)
метод выполняется послеnotify()
метод,Так что вы можете доказать звонокsleep()
метод не снимает блокировку.
расширение знаний
1. В чем разница между сном и ожиданием?
sleep
иwait
Это почти обязательный вопрос на всех собеседованиях, но не кажется таким уж простым ответить на него правильно.
заsleep
иwait
Разница, обычный ответ таков:
- ожидание должно использоваться с синхронизацией, а сон — нет;
- Поток, входящий в состояние ожидания, может быть разбужен потоками notify и notifyAll, в то время как поток в спящем состоянии не может быть разбужен методом notify;
- ожидание обычно выполняется условно, поток будет оставаться в состоянии ожидания до тех пор, пока определенное условие не станет истинным, но сон только усыпляет ваш поток;
- Метод ожидания снимает блокировку объекта, а метод сна — нет.
Но выше ответа явно не хватает важного различия, вызывающегоwait
метод, нить становитсяWATING
состояние при вызовеsleep
метод, нить становитсяTIMED_WAITING
государство.
2. Можно ли использовать ожидание в статических методах? Зачем?
нет потому чтоwait
Метод является методом экземпляра (неstatic
метод), поэтому не может быть использован вstatic
Исходный код выглядит следующим образом:
public final void wait() throws InterruptedException {
wait(0);
}
3. Можно ли использовать ожидание/уведомление без синхронизации? Зачем?
Нет, потому что не совпадаетsynchronized
При использовании программа сообщит об ошибке, как показано на следующем рисунке:
Более глубокая причина заключается в том, что не добавляяsynchronized
Слова вызовут потерю пробуждения, потерю пробуждения, поиск деталей:nuggets.capable/post/684490…
Суммировать
В этой статье мы проходимsynchronized
Заблокируйте тот же объект, чтобы проверитьwait
иsleep
методом, а затем доказать последовательностью результатов выполнения:wait
метод снимает блокировку, аsleep
метод не. Мы также рассказали о некоторыхwait
иsleep
общие вопросы интервью, я надеюсь, что эта статья может помочь вам.
Обратите внимание на общественный номер»Сообщество китайского языка Java” для большего количества отличного контента.