Короткий ответ Потому что эти методы работают с монитором объекта, а не с потоком: поток ожидает на конкретном объекте-«замке», и уведомление тоже отправляется через объект. Встроенный монитор есть у любого наследника Object, поэтому естественно разместить методы ожидания и уведомления в самом Object, чтобы их можно было вызывать для любого объекта-монитора. Как это работает подробнее Механика такая: поток вызывает someObject.wait() из синхронизированного блока по someObject, освобождает его монитор и засыпает, а другой поток вызывает notify()/notifyAll() на том же объекте, чтобы разбудить ожидающих. Именно привязка к объекту позволяет независимо синхронизироваться на разных «замках»: ожидание на одном объекте не мешает потокам работать с другим. notify() будит один произвольный поток из очереди ожидания на мониторе, notifyAll() — все ожидающие, после чего они конкурируют за монитор. notifyAll() безопаснее в большинстве сценариев: он снижает риск «потерянного уведомления». Пример кода Что использовать на прак