Я часто просматриваю. Что касается уведомления и уведомления в Java, у людей часто есть следующие заявления:
Уведомление будет уведомлять только о ожидании объекта, в то время как уведомление уведомит все ожидающие объекты, и все объекты будут продолжать работать.
И кажется, что есть примеры, чтобы доказать это. Приведенное выше утверждение можно сказать, что является правильным или нет. Причина в том, что один из них очень важен. Официальное заявление заключается в следующем:
Подождите, уведомлять, уведомлять:
Этот метод должен вызывать только потоком, который является владельцем этого монитора объекта. Поток может стать владельцем этого монитора объекта одним из трех способов:
Выполнив метод синхронного экземпляра этого объекта.
Тело синхронизированного оператора выполняется путем выполнения синхронизированного оператора по этому объекту.
Для объектов класса типа вы можете выполнить синхронные статические методы класса.
Только один поток имеет монитор объекта одновременно.
Приведенное выше утверждение выдержек из Javadoc. Это означает, что при вызове должен быть проведен монитор объекта (то есть блокировку), который мы можем понимать, работая в рамках синхронизированного метода. Тогда неявное значение этого утверждения заключается в том, что если вы хотите продолжить блок кода, содержащийся в блоке синхронизации, вам необходимо повторно приобретать блокировку. Это предложение описано в Javadoc:
ждать
Этот метод приводит к тому, что текущий поток (называемый T) помещается в набор ожидания объекта, а затем отказывается от всех требований к синхронизации на этом объекте. Для целей планирования потоков нить T отключена и находится в спячке до того, как произойдет одна из следующих четырех ситуаций:
Некоторые другие потоки вызывает метод уведомления этого объекта, а поток T выбирается в качестве потока пробуждения.
Некоторый другой поток вызывает метод notifyall этого объекта.
Некоторые другие потоки прерывают нить T.
Приблизительно указанное фактическое время было достигнуто. Однако, если тайм -аут равен нулю, фактическое время не учитывается, и поток будет ждать, пока не будет получено уведомление.
Затем поток T удаляется из набора ожидания объекта, и планирование потока выполняется снова. Затем поток конкурирует с другими потоками общепринятым способом получить право синхронизировать объект; Как только контроль над объектом будет
Ситуация, когда метод есть. Затем Thread T возвращается из вызова к методу ожидания. Следовательно, при возвращении из метода ожидания состояние синхронизации объекта и потока T точно так же, как при вызове метода ожидания.
То есть замок должен быть повторно приобретен, так что для уведомления все потоки были уведомлены. Тем не менее, эти потоки будут конкурировать, и только один поток успешно приобретет блокировку. До того, как этот поток будет выполнен, другие потоки должны ждать (но здесь нет необходимости уведомлять уведомление, потому что оно является уведомлением, и для приобретения блокировки необходимо только приобрести блокировку). Существует следующий код, который может воспроизвести это явление.
Во -первых, определите класс потоков, который может работать следующим образом:
Частный статический конечный объект obj = new Object (); Статический класс R реализует Runnable {int i; R (int i) {this.i = i; } public void run () {try {synchronized (obj) {System.out.println ("thread->" + i + "wating"); obj.wait (); System.out.println ("Thread->" + i + "running"); Thread.sleep (30000); }} catch (Exception e) {e.printstackTrace (); }}} Обратите внимание на внутреннюю часть метода прогона выше. После ожидания () мы распечатываем предложение, а затем сделаем паузу текущего кода в течение 30 секунд. Что касается метода сна, это описано следующим образом:
Поток не теряет владения какими -либо мониторами.
То есть замок все еще удерживается.
Затем определите основной метод для запуска этих потоков следующим образом:
Thread [] rs = новый поток [10]; for (int i = 0; i <10; i ++) {rs [i] = новый поток (новый r (i)); } for (Thread r: rs) {r.Start (); } Thread.sleep (5000); синхронизированный (obj) {obj.notifyall (); }Мы определяем 10 потоков, а затем запускаем их все. Поскольку есть ожидание, 10 потоков будут ждать после печати "Start Run". Тогда основной метод вызовов уведомлений. Вывод здесь появится следующим образом:
Thread-> 0 В ожидании потока-> 4 В ожидании потока-> 5 В ожидании потока-> 3 В ожидании потока-> 2 В ожидании потока-> 1 В ожидании потока-> 6 В ожидании потока-> 7 В ожидании потока-> 8 В ожидании потока-> 9 В ожидании потока-> 9 Запуск.
... никаких других выводов в течение 30 секунд
На приведенном выше выводе, после ожидания, только один поток выводит оператор «Запуск», и в течение определенного периода времени (здесь 30 секунд) не будет никакого другого вывода. То есть другие потоки не будут выходить между блоками, удерживаемыми текущим кодом.
Окончательный вывод: если поток ожидания хочет продолжить работу, он должен соответствовать двум условиям:
Другой поток уведомление или уведомление было уведомлено, и текущий поток был уведомлен.
После соревнования с другими потоками для блокировки было успешно получено два условия для блокировки, и ни одно из них не пропустил. Фактически, на уровне реализации уведомление и уведомление о том же эффекте, и поток будет продолжать работать. Но уведомление освобождено. Необходимость уведомления других потоков после запуска потока, потому что он был уведомлен. Когда использовать уведомление и когда использовать notifyall, это зависит от фактической ситуации.
Выше приведено сборник информации для Java уведомления и уведомления. Мы будем продолжать добавлять соответствующую информацию в будущем. Спасибо за поддержку этого сайта!