Java notify와 notifyAll의 차이점은 동일합니다.

자주 위로 돌아다녀요. 자바에서 notify와 notifyAll에 대해 다음과 같은 의견이 자주 있습니다.
notify는 기다리는 대상만 알려주고, notifyAll은 기다리는 대상만 알려주며, 모든 대상은 계속 실행됩니다.
그리고 증명할 수 있는 예가 있는 것 같다.위의 견해는 옳다고 말할 수도 있고, 틀렸다고 말할 수도 있다.그 이유는 그 중 하나는 매우 관건적이다. 정부의 견해는 다음과 같다.
wait,notify,notifyAll:
이 방법은 이 대상 모니터의 소유자로서의 루트로만 호출되어야 합니다.다음 세 가지 방법 중 하나를 통해 이 대상 모니터의 소유자가 될 수 있습니다
:
이 대상의 동기화 실례 방법을 실행합니다.
이 대상에 동기화된synchronized 문장의 본문을 실행합니다.
Class 유형의 객체에 대해 이 유형의 동기화 정적 방법을 실행할 수 있습니다. 
한 번에 하나의 라인만 대상을 가진 모니터가 있습니다.
이상의 견해는javadoc에서 발췌한 것이다.호출 중 대상 모니터(즉 자물쇠)를 소지해야 한다는 뜻으로synchronized 방법에서 실행해야 한다는 것을 이해할 수 있습니다.그러면 이 말의 은밀한 의미, 즉 동기화 블록에 포함된 코드 블록을 계속하려면 자물쇠를 다시 가져와야 한다는 것이다.이 말은 javadoc에서 다음과 같이 설명합니다.
wait
이 방법으로 현재 스레드(T라고 함)는 대상의 대기 집합에 자신을 놓고 이 대상의 모든 동기화 요구를 포기합니다.스레드 스케줄링에서
목적, 다음 네 가지 상황 중 하나가 발생하기 전에 스레드 T가 비활성화되고 휴면 상태입니다.
다른 어떤 스레드는 이 대상의 notify 방법을 호출하고, 스레드 T는 공교롭게도 깨우는 스레드로 선택되었습니다.
다른 스레드는 이 대상의 notifyAll 방법을 호출합니다.
다른 어떤 스레드는 T를 중단합니다.
대략 지정된 실제 시간에 도달했다.단, 타임아웃이 0이면 실제 시간을 고려하지 않고 알림을 받기 전까지 이 라인은 기다립니다.
그리고 대상의 대기 집합에서 스레드 T를 삭제하고 다시 스레드 스케줄링을 합니다.그리고 이 스레드는 일반적인 방식으로 다른 스레드와 경쟁하여 이 쌍을 얻는다
상동기화의 권리;일단 이 대상에 대한 제어권을 얻게 되면, 이 대상의 모든 동기화 성명은 이전 상태로 회복됩니다. 이것은wait 호출입니다.
방법시의 상황.그리고 스레드 T는wait 방법의 호출에서 되돌아옵니다.따라서wait 방법에서 돌아올 때 이 대상과 스레드 T의 동기화 상태와 조정
wait 방법을 사용할 때의 상황은 완전히 같다.
자물쇠를 다시 가져와야 합니다. notifyAll에 있어서 모든 라인이 통지되었지만.그러나 이 라인들은 모두 경쟁을 하고 하나의 라인만 자물쇠를 얻는 데 성공할 것이다. 이 라인이 실행되기 전에 다른 라인은 반드시 기다려야 한다. (단지 여기는 더 이상 notify All 알림이 필요 없다. 왜냐하면 이미 notify All이 있기 때문에 자물쇠를 얻을 수 없기 때문이다.) 다음과 같은 코드가 있어서 이 현상을 재현할 수 있다.
먼저 다음과 같이 실행 가능한 스레드 클래스를 정의합니다.

private static final Object obj = new Object();
  static class R implements Runnable {
    int i;
 
    R(int i) {
      this.i = i;
    }
 
    public void run() {
      try {
        synchronized(obj) {
          System.out.println(" -> " + i + "  ");
          obj.wait();
          System.out.println(" -> " + i + "  ");
          Thread.sleep(30000);
        }
      } catch(Exception e) {
        e.printStackTrace();
      }
    }
  }
위의run 방법 내부를 주의하십시오. 우리는wait() 다음에 한 마디를 인쇄한 다음 현재 코드를 30초 동안 정지합니다.sleep 방법에 대해 다음과 같이 설명합니다.
이 스레드는 모니터의 소속권을 잃지 않습니다.
여전히 자물쇠를 가지고 있다.
그런 다음 다음과 같이 main 방법을 정의합니다.

Thread[] rs = new Thread[10];
    for(int i = 0;i < 10;i++) {
      rs[i] = new Thread(new R(i));
    }
    for(Thread r : rs) {
      r.start();
    }
 
    Thread.sleep(5000);
    synchronized(obj) {
      obj.notifyAll();
    }
우리는 10개의 라인을 정의한 후에 모두 운행했다.wait가 있기 때문에, 10개의 스레드가 "실행 시작"을 출력한 후에 기다립니다.그리고 main 방법은 notifyAll을 호출합니다.여기서 출력은 다음과 같습니다.
스레드 -> 0 대기 중
스레드 -> 4 대기 중
스레드 -> 5 대기 중
스레드 -> 3 대기 중
스레드 -> 2 대기 중
스레드 -> 1 대기 중
스레드 -> 6 대기 중
스레드 -> 7 대기 중
스레드 -> 8 대기 중
스레드 -> 9 대기 중
스레드 -> 9 실행 중
...30초 동안 다른 출력이 없습니다
위의 출력에서wait 이후에 하나의 스레드 출력만 실행되고 있습니다. 그리고 일정 시간 동안 (여기는 30초) 다른 출력은 없습니다.즉, 현재 코드가 자물쇠를 가지고 있는 동안 다른 라인은 출력되지 않는다는 것을 나타낸다.
마지막 결론은wait의 라인에 의해 계속 운행하려면 두 가지 조건을 만족시켜야 한다는 것이다.
다른 노드 notify 또는 notify All에서 현재 노드가 통지되었습니다.
다른 라인과 자물쇠 경쟁을 통해 자물쇠 두 가지 조건을 얻는 데 성공했고 하나가 빠지면 안 된다.사실 실현 차원에서 notify와 notifyAll은 모두 같은 효과에 도달하고 하나의 라인이 계속 운행될 것이다.그러나 notifyAll은 면제되었습니다. 라인이 실행되면 다른 라인을 알려야 합니다. 이미 통지했기 때문입니다.notify를 언제 사용하는지, notifyAll을 언제 사용하는지, 이것은 실제 상황을 보아야 한다.
지금까지 Java notify와 Notify All에 대한 자료 정리를 하였으며, 계속해서 관련 자료를 보충하였습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기