나는 종종 탐색합니다. Java의 Notify 및 Notifyall과 관련하여 사람들은 종종 다음과 같은 진술을합니다.
Notify는 대기 대기 대기 만 알리지만 Notifyall은 모든 객체를 대기하고 모든 객체가 계속 실행됩니다.
그리고 그것을 증명할 예가있는 것 같습니다. 위의 진술은 정확하다고 말할 수 있습니다. 그 이유는 그들 중 하나가 매우 중요하기 때문입니다. 공식 진술은 다음과 같습니다.
잠깐만, 알림, notifyall :
이 메소드는이 객체 모니터의 소유자 인 스레드에서만 호출해야합니다. 스레드는 세 가지 방법 중 하나 에서이 객체 모니터의 소유자가 될 수 있습니다.
이 객체의 동기 인스턴스 메소드를 실행함으로써.
동기화 된 문의 본문은이 객체에서 동기화 된 문을 실행하여 실행됩니다.
유형 클래스의 객체의 경우 클래스의 동기 정적 메소드를 실행할 수 있습니다.
하나의 스레드 만 한 번에 객체 모니터가 있습니다.
위의 진술은 Javadoc에서 발췌 한 것입니다. 즉, 통화에서 객체 모니터 (즉, 잠금)를 유지해야하며 동기화 된 메소드 내에서 실행되는 것으로 이해할 수 있습니다. 그런 다음이 진술의 암시 적 의미는 동기화 블록에 포함 된 코드 블록을 계속하려면 잠금을 다시 인출해야한다는 것입니다. 이 문장은 Javadoc에 설명되어 있습니다.
기다리다
이 방법으로 인해 현재 스레드 (T)가 대기 대기 세트에 자체적으로 배치 한 다음이 객체의 모든 동기화 요구 사항을 포기하게됩니다. 스레드 스케줄링 목적으로 스레드 T는 비활성화되어 다음 4 가지 상황 중 하나가 발생하기 전에 동면 중입니다.
일부 다른 스레드는이 객체의 알림 메소드를 호출하고 스레드 T는 선택적으로 웨이크 업 스레드로 선택됩니다.
다른 스레드는이 객체의 Notifyall 메소드를 호출합니다.
다른 스레드는 스레드 T를 인터럽트합니다.
지정된 실제 시간에 대략 도달했습니다. 그러나 타임 아웃이 0 인 경우 실제 시간이 고려되지 않으며 알림이 얻을 때까지 스레드가 대기합니다.
그런 다음 객체의 대기 세트에서 스레드 t를 삭제하고 스레드 스케줄링이 다시 수행됩니다. 그런 다음 스레드는 객체의 동기화 권리를 얻기 위해 기존의 방식으로 다른 스레드와 경쟁합니다. 객체에 대한 제어가 얻어지면 객체에 대한 모든 동기화 선언이 이전 상태로 복원됩니다.
방법이있는 상황. 그런 다음 스레드 T는 호출에서 대기 방법으로 돌아갑니다. 따라서 대기 방법에서 돌아올 때 객체 및 스레드 T의 동기화 상태는 대기 방법을 호출 할 때와 정확히 동일합니다.
즉, 잠금 장치를 다시 접수하여 NotifyAll의 경우 모든 스레드에 알림을 받았습니다. 그러나이 스레드는 경쟁하고 하나의 스레드만이 잠금을 성공적으로 얻습니다. 이 스레드가 실행되기 전에 다른 스레드는 대기해야합니다 (그러나 여기서 알림 알림은 알려줄 필요가 없으며 잠금을 얻는 것이 필요합니다). 이 현상을 재현 할 수있는 다음 코드가 있습니다.
먼저 다음과 같이 실행할 수있는 스레드 클래스를 정의하십시오.
개인 정적 최종 객체 obj = new Object (); 정적 클래스 r은 실행 가능한 {int i; r (int i) {this.i = i; } public void run () {try {synchronized (obj) {system.out.println ( "스레드->" + i + "대기"); obj.wait (); System.out.println ( "스레드->" + i + "running"); Thread.sleep (30000); }} catch (예외 e) {e.printstacktrace (); }}} 위의 실행 방법의 내부에주의하십시오. 대기 () 후 문장을 인쇄 한 다음 현재 코드를 30 초 동안 일시 중지합니다. 수면 방법과 관련하여 다음과 같이 설명됩니다.
스레드는 모니터의 소유권을 잃지 않습니다.
즉, 자물쇠는 여전히 고정되어 있습니다.
그런 다음 다음 스레드를 실행하는 기본 메소드를 다음과 같이 정의합니다.
스레드 [] rs = 새 스레드 [10]; for (int i = 0; i <10; i ++) {rs [i] = 새 스레드 (new r (i)); } for (스레드 r : rs) {r.start (); } thread.sleep (5000); 동기화 (obj) {obj.notifyall (); }우리는 10 개의 스레드를 정의한 다음 모두 실행합니다. 대기가 있기 때문에 10 개의 스레드가 "시작 실행"을 인쇄 한 후 대기합니다. 그런 다음 기본 메소드는 NotifyAll을 호출합니다. 여기의 출력은 다음과 같이 나타납니다.
스레드-> 0 스레드 대기-> 4 스레드 대기-> 5 스레드 대기-> 3 스레드 대기-> 2 스레드 대기-> 1 스레드 대기-> 6 스레드를 기다리는 대기-> 7 스레드를 기다리는 대기-> 9 스레드 대기-> 9 실행
... 30 초 이내에 다른 출력이 없습니다
위의 출력에서 대기 후 하나의 스레드 만 "실행"문을 출력하고 일정 기간 (30 초)에 다른 출력이 없습니다. 즉, 다른 스레드는 현재 코드에서 보유한 잠금 장치간에 출력되지 않습니다.
마지막 결론은 다음과 같습니다. 대기 실이 계속 실행되기를 원한다면 두 가지 조건을 충족해야합니다.
다른 스레드 알림 또는 NotifyAll에 알림이 표시되었으며 현재 스레드에 알림을 받았습니다.
잠금을 위해 다른 스레드와 경쟁 한 후, 잠금을 위해 두 가지 조건이 성공적으로 얻어졌으며 그 중 어느 것도 누락되지 않았습니다. 실제로, 구현 수준에서, 알림 및 알림은 동일한 효과를 달성하고 스레드가 계속 실행됩니다. 그러나 Notifyall은 면제됩니다. 스레드가 실행 된 후 다른 스레드에 알림이 통지되었으므로 다른 스레드에 알릴 필요가 있습니다. Notify를 사용하고 NotifyAll을 사용할 때 실제 상황에 따라 다릅니다.
위는 Java Notify 및 Notifyall에 대한 정보를 편집 한 것입니다. 우리는 향후 관련 정보를 계속 추가 할 것입니다. 이 웹 사이트를 지원 해주셔서 감사합니다!