JavaRush /Курсы /Java Multithreading /Другие методы класса Thread (sleep, yield…)

Другие методы класса Thread (sleep, yield…)

Java Multithreading
5 уровень , 10 лекция
Открыта

— Привет, Амиго!

А теперь немного расскажу про методы sleep, yield, join.

— Это скучно. Я тут нашел вопрос к собеседованию «Чем отличаются методы yield(), sleep(), wait()?». Может расскажешь?

— Не вопрос. Начну с того, что это три совершенно разных метода.

1) sleep(timeout) – останавливает текущую нить (в которой sleep был вызван) на timeout миллисекунд. Нить при этом переходит в состояние TIMED_WAITING. Метод может завершиться раньше, если был установлен флаг isInterrupted.

Пример Описание
Thread.sleep(500);
Текущая нить приостанавливает свою работу на 500 миллисекунд – 0.5 секунды.

2) yield() – текущая нить «пропускает свой ход». Нить из состояния running переходит в состояние ready, а Java-машина приступает к выполнению следующей нити. Состояния running & ready – это подсостояния состояния RUNNABLE.

Пример Описание
Thread.yield();
Текущая нить «пропускает свой ход» — Java сразу переключается на выполнение следующей нити.

3) wait(timeout) – это одна из версий метода wait() – версия с таймаутом. Метод wait можно вызвать только внутри блока synchronized у объекта-мютекса, который был «залочен (заблокирован)» текущей нитью, в противном случае метод выкинет исключение IllegalMonitorStateException.

В результате вызова этого метода, блокировка с объекта-мютекса снимается, и он становится доступен для захвата и блокировки другой нитью. При этом нить переходит в состояние WAITING для метода wait() без параметров, но в состояние TIMED_WAITING для метода wait(timeout).

Пример Описание
Object monitor = getMonitor();
synchronized(monitor)
{
 …
 monitor.wait(500);
 …
}
При вызове метода wait, текущая нить снимает блокировку с объекта monitor, и засыпает на 500 миллисекунд. Объект monitor может быть захвачен другой нитью.
Через 500 миллисекунд нить проснется и если monitor не был занят, то захватит его и продолжит работу.
Если монитор окажется занят другой нитью, текущая нить перейдет в состояние BLOCKED.

4) join(timeout)

Этого метода не было в твоем вопросе, но он есть в моих планах, так что расскажу и про него. При вызове метода join() или join(timeout) текущая нить как бы «присоединяется» к нити, у объекта которой был вызван данный метод. Текущая нить засыпает и ждет окончания нити, к которой она присоединилась (чей метод join() был вызван).

При этом текущая нить переходит в состояние WAITING для метода join и в состояние TIMED_WAITING для метода join(timeout).

Пример Описание
Thread thread = getWorkThread();
thread.join(500);
Текущая нить присоединится к нити thread и будет ждать ее окончания.
Но отсоединится через 500 миллисекунд и продолжит работу.

timeout в методах wait(timeout) и join(timeout) значит, что метод засыпает, ждет чего-то, но не дольше чем timeout миллисекунд. После чего просыпается.

— Такое ощущение, что единственное, что есть общего у этих методов – это timeout. Но делают они совершенно разные вещи.

— Так оно и есть.

Комментарии (45)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
G L Уровень 38
25 апреля 2025
Про join путал, но в итоге разобрался. Например, у нас есть main-метод который выполняется. Код доходит до строчки thread1.join();. Main останавливается и не выполняется, пока нить thread1 не закончит свою работу. После того как нить thread1 закончила работу, свою работу возобновляет main-нить и выполняет оставшийся код. Можно сказать что одна нить коннектиться к другой и теперь в роли обсервера наблюдает и ждет пока та закнчит свою работу, а потом только после этого возращается к своей.
Алексей Уровень 7
17 ноября 2024
"При вызове метода join() или join(timeout) текущая нить как бы «присоединяется» к нити, у объекта которой был вызван данный метод. Текущая нить засыпает и ждет окончания нити, к которой она присоединилась (чей метод join() был вызван)." Простите, что???
very junior java developer Уровень 51
21 мая 2023
В этой вырезке нити называют потоками, но я думаю что для большинства людей это не будет иметь значения: Метод yield в Java используется для явного указания, что текущий поток готов отдать свою текущую обработку другим потокам. Однако, начиная с Java 5, метод yield потерял свою значимость и его использование обычно не рекомендуется. Когда поток вызывает метод yield, он сообщает планировщику потоков (thread scheduler), что он готов уступить процессорное время другим потокам. Планировщик потоков решает, какой поток будет следующим получать процессорное время. Однако, работа планировщика потоков и его стратегия планирования зависят от конкретной реализации JVM и операционной системы, и поэтому поведение метода yield может быть непредсказуемым. Обычно нет необходимости использовать метод yield, так как планировщик потоков самостоятельно распределяет процессорное время между потоками.
25 декабря 2022
yield() – текущая нить «пропускает свой ход» А может и не пропускает, ведь кто мы такие чтобы решать что будет делать программа в runtime...
Kurama Уровень 50
9 ноября 2022
А смысл вызывать wait() у мьютекса, а не у нити Пока не понимаю какой в этом толк
Pavel V. Уровень 41
5 декабря 2022
Нитям нужны объекты, на которых будет проходить синхронизация. Они между собой никак иначе не общаются. Вся соль в том, что метод wait() сообщает второй нити, что лок (мьютекс) снят, и она может спокойно заходить в метод.
Kurama Уровень 50
5 декабря 2022
Я просто думал, что нить натыкается на wait() в коде и засыпает. wait() же можно вызвать в синхронайзд блоке, очевидно, что нить уже захватила определённый мьютекс, зачем ещё раз это указывать Разве что нить удерживает несколько мьютексов, не знаю, возможно ли это вообще
Maks Panteleev Уровень 41
21 мая 2021
а разве wait работает без notify?
Sasha Уровень 2
20 августа 2021
nope
Dolivo Serg Уровень 40
10 ноября 2021
wait(timeout)
12 марта 2021
все что я понял. любой из этих методов не гарантирует, что нить проснется и получит управление Ровно через таймаут, т.к. очередь еще не пришла и соседи кушают. остальные тонкости в комментах ниже...
Max Pankov Уровень 31
16 октября 2020
и еще не написали, что timeout является признаком дурного тона и говорит о криво написанной программе
12 марта 2021
и как изобразить без таймаута например ход секундной стрелки? любое утверждение порождается дабы самоутвердиться. Если ты выкопал яму эксковатором, всем вроде плевать как ты ее копал, но при этом всегда будут такие кому захочется бегать вокруг и орать "неумеха, слабак, дурной тон поддерживает", лопату держать неумеет. ;)
LokiLaufeyson Уровень 41
14 апреля 2021
Он имел ввиду, что тайм-аут в общем случае не должен использоваться для координации потоков. Например, нелепо, если один поток зависит от результатов работы второго, и в нём установлен тайм-аут на 10 секунд, чтобы второй поток точно успел отработать. Но есть конкретные задачи, в которых он уместен - например, мы ищем оптимальное решение какой-то задачи, и пользователь не готов ждать больше 5 секунд. В таком случае, мы либо вернём оптимальное решение, либо после 5 секунд вернём самое лучшее, которое нашли
Nursultan Уровень 31
11 июня 2020
Для метода yield на docs.oracle.com: A hint to the scheduler that the current thread is willing to yield its current use of a processor. Итог: "планировщик потоков" сам решает, необязательно, что будет переключение на другую нить.
Wladyslaw Уровень 41 Master
29 декабря 2019
Забыли еще про notify() и notifyAll() Если нить хочет захватить монитор, но он уже занят - она попадает в подмножество BLOCKED. Если нить захватила монитор и вызвала метод wait() - она перейдет в подмножество WAITING, а монитор будет освобожден и другая нить из BLOCKED сможет его захватить. Так вот notify() и notifyAll() переводит одну/все нити из состояния WAITING в активное состояние, после попытки захватить монитор они его либо получат, либо перейдут в состояние BLOCKED
Sergey Semendyaev Уровень 41
7 марта 2020
Почему сразу забыли?