Почему методы wait()
и notify()
, объявленные в классе Object
, а не класс Thread
?
Почему wait() и notify() объявлены в классе Java Object?
Ответ 1
Потому что вы ожидаете от данного объекта (или, в частности, его монитора) использовать эту функциональность.
Я думаю, вы можете ошибаться в том, как эти методы работают. Они не просто на уровне детализации, т.е. Это не случай просто вызова wait()
и разбудки при следующем вызове notify()
. Скорее всего, вы всегда вызываете wait()
на конкретный объект и будете только разбуждаться вызовами notify
на этом объекте.
Это хорошо, потому что в противном случае примитивы concurrency просто не будут масштабироваться; это было бы эквивалентно наличию глобальных пространств имен, поскольку любые вызовы notify()
в любом месте вашей программы могли бы испортить какой-либо параллельный код, поскольку они активировали бы блокировку потоков при вызове wait()
. Отсюда причина, по которой вы называете их определенным объектом; он дает контекст для пары ожидания ожидания, чтобы работать, поэтому, когда вы вызываете myBlockingObject.notify()
, на частном объекте вы можете быть уверены, что только пробуждаете потоки, называющие методы ожидания в своем классе. Некоторый поток Spring, который может ждать на другом объекте, не будет разбужен этим вызовом и наоборот.
Изменить: Или обратиться к нему с другой точки зрения - я ожидаю от вашего вопроса, что, как вы думали, вы получите дескриптор ожидающего потока и вызовите notify()
в этом потоке, чтобы разбудить его. Причина, по которой это не так, заключается в том, что вам придется самому заниматься домашним хозяйством. Поток, который будет ждать, должен будет опубликовать ссылку на себя где-нибудь, что другие потоки могли бы увидеть это; это должно быть правильно синхронизировано для обеспечения согласованности и видимости. И когда вы хотите просыпать нить, вам нужно будет справиться с этой ссылкой, пробудить ее и удалить ее там, где вы ее читали. Там задействовано гораздо больше ручных строительных лесов и гораздо больше шансов поступить с ним (особенно в параллельной среде) по сравнению с просто вызовом myObj.wait()
в спящем потоке, а затем myObj.notify()
в waker thread.
Ответ 2
Самая простая и очевидная причина в том, что любой объект (а не только поток) может быть монитором для потока. Ожидание и уведомление вызываются на монитор. Текущая резьба проверяется монитором. Поэтому методы wait и notify находятся в Object и not Thread
Ответ 3
Потому что только один поток за один раз может владеть монитором объекта, и этот монитор - это то, что потоки ожидают или уведомляют. Если вы читаете javadoc для Object.notify()
и Object.wait()
, это описано подробно.
Ответ 4
Механизм синхронизации включает в себя концепцию - монитор объекта. Когда вызывается wait(), монитор запрашивается, и дальнейшее выполнение приостанавливается до тех пор, пока не будет получен монитор или не произойдет InterruptedException. Когда вызывается уведомление(), монитор отпускается.
Возьмем сценарий, если wait() и notify() были помещены в класс Thread вместо класса Object. В какой-то момент кода вызывается currentThread.wait()
, а затем обращается к объекту anObject
.
//.........
currentThread.wait();
anObject.setValue(1);
//.........
При вызове currentThread.wait() отслеживается монитор currentThread
, и дальнейшее выполнение не выполняется до тех пор, пока не будет обнаружен монитор или не будет прервано исключение. Теперь, находясь в состоянии ожидания, если метод foo()
другого объекта anotherObject
, находящийся в currentThread
, вызывается из другого потока, он застревает, даже если вызываемый метод foo()
не имеет доступа к anObject
. Если первый метод wait() был вызван на anObject
, вместо самого потока другие вызовы методов (не обращаясь к anObject
) на объекты, находящиеся в одном и том же потоке, не застряли.
Таким образом, вызовы методов wait() и notify() для класса Object (или его подклассов) обеспечивают более высокий concurrency и то, почему эти методы находятся в классе Object, а не в классе Thread.
Ответ 5
Несколько других ответов используют слово "монитор", но никто не объясняет, что это значит.
Название "монитор" было введено еще в 1970-х годах, и оно ссылалось на объект, у которого была собственная внутренняя блокировка, и связанный механизм ожидания/уведомления. https://en.wikipedia.org/wiki/Monitor_%28synchronization%29
Двадцать лет спустя, был краткий момент времени, когда настольные, многопроцессорные компьютеры были новыми, и было модно думать, что правильным способом разработки программного обеспечения для них было бы создание объектно-ориентированных программ, в которых каждый Объектом был монитор.
Оказывается, это была не такая полезная идея, но этот короткий момент происходит именно тогда, когда был изобретен язык программирования Java.
Ответ 6
Прочитайте здесь для объяснения ожидания и уведомления.
Лучше избегать их, однако, в ваших приложениях и использовать новый пакет java.util.concurrent.
Ответ 7
Я поставлю его простым способом:
Чтобы вызвать wait() или notify(), вам необходимо владеть объектным монитором - это означает, что wait() или notify() должны присутствовать в синхронизированном блоке
synchronized(monitorObj){
monitorObj.wait() or even notify
}
Именно поэтому эти методы присутствуют в классе объектов
Ответ 8
Это связано с тем, что эти методы предназначены для связи между потоками, а interthreadcommunication происходит с помощью блокировок, но блокировки связаны с объектами. Если он находится в классе объектов.
Ответ 9
Методы Wait и Notify используют связь между двумя потоками в Java. Таким образом, класс Object является правильным местом, чтобы сделать их доступными для каждого объекта в Java.
Другая причина заключается в том, что блокировки доступны для каждого объекта. Нитки требуют блокировки, и они ждут блокировки, они не знают, какие потоки содержат блокировку, а они просто знают, что блокировка удерживается каким-то потоком, и они должны ждать блокировки вместо того, чтобы знать, какой поток находится внутри синхронизированного блока, и попросить их освободить блокировка