Java 에서 notify()와 notifyAll()의 사용 차이

notify()와 notify All()은 어떤 차이 가 있 습 니까?
두 개념 을 먼저 해석 하 다.
4.567917 대기 탱크:하나의 스 레 드 A 가 특정한 대상 의 wait()방법 을 호출 했다 고 가정 하면 스 레 드 A 는 이 대상 의 자 물 쇠 를 풀 고 이 대상 의 대기 탱크 에 들 어가 서 대기 탱크 의 스 레 드 가 이 대상 의 자 물 쇠 를 경쟁 하지 않 습 니 다4.567917.잠 금 풀:대상 의 자 물 쇠 를 가 져 와 야 스 레 드 가 대상 의 synchronized 코드 를 실행 할 수 있 습 니 다.대상 의 자 물 쇠 는 매번 하나의 스 레 드 만 얻 을 수 있 고 다른 스 레 드 는 잠 금 풀 에서 만 기다 릴 수 있 습 니 다그리고 notify 와 notify All 의 차 이 를 말씀 드 리 겠 습 니 다.
4.567917.스 레 드 가 대상 의 wait()방법 을 호출 하면 스 레 드 는 이 대상 의 대기 탱크 에 있 고 대기 탱크 의 스 레 드 는 이 대상 의 자 물 쇠 를 경쟁 하지 않 습 니 다
  • 스 레 드 가 대상 의 notify All()방법(모든 wait 스 레 드 를 깨 우 는 것)이나 notify()방법(하나의 wait 스 레 드 만 무 작위 로 깨 우 는 것)이 있 으 면 깨 워 진 스 레 드 는 이 대상 의 잠 금 풀 에 들 어가 고 잠 금 풀 의 스 레 드 는 이 대상 의 잠 금 을 경쟁 합 니 다.즉,notify 를 호출 한 후 하나의 스 레 드 가 대기 탱크 에서 잠 금 탱크 에 들 어가 면 notify All 은 이 대상 이 대기 탱크 안의 모든 스 레 드 를 잠 금 탱크 로 이동 시 켜 잠 금 경쟁 을 기다 리 는 것 이다
  • 4.567917.우선 순위 가 높 은 스 레 드 가 대상 잠 금 에 경쟁 할 확률 이 높다.만약 에 특정한 스 레 드 가 이 대상 잠 금 에 경쟁 하지 않 으 면 잠 금 풀 에 남아 있 고 스 레 드 가 wait()방법 을 다시 호출 해 야 대기 풀 로 다시 돌아 갈 수 있다.그리고 대상 잠 금 에 경쟁 하 는 스 레 드 는 synchronized 코드 블록 을 실행 할 때 까지 계속 실행 합 니 다.이 때 잠 금 탱크 의 스 레 드 는 이 대상 잠 금 을 계속 경쟁 합 니 다다시 말 하면 스 레 드 를 깨 우 는 것 은 스 레 드 를 대기 탱크 에서 잠 금 탱크 로 이동 시 키 는 것 이 라 고 할 수 있 습 니 다.notify All 호출 후 모든 스 레 드 를 대기 탱크 에서 잠 금 탱크 로 옮 긴 다음 에 잠 금 경쟁 에 참여 하고 경쟁 이 성공 하면 계속 실 행 됩 니 다.성공 하지 못 하면 잠 금 탱크 에 남아 잠 금 이 풀 리 기 를 기다 린 후에 다시 경쟁 에 참여 합 니 다.notify 는 하나의 스 레 드 만 깨 울 수 있 습 니 다.
    이러한 이론 적 기반 이 있 으 면 뒤의 notify 는 잠 금 을 초래 할 수 있 고 notify All 은 그렇지 않 은 예 로 해석 할 수 있다.
    테스트 코드
    
    public class TestNotifyNotifyAll {
     
     private static Object obj = new Object();
     
     public static void main(String[] args) {
      
      //   RunnableImplA wait()        
      Thread t1 = new Thread(new RunnableImplA(obj));
      Thread t2 = new Thread(new RunnableImplA(obj));
      t1.start();
      t2.start();
      
      //RunnableImplB notify()
      Thread t3 = new Thread(new RunnableImplB(obj));
      t3.start();
      
      
    //  //RunnableImplC notifyAll()
    //  Thread t4 = new Thread(new RunnableImplC(obj));
    //  t4.start();
     }
     
    }
     
     
    class RunnableImplA implements Runnable {
     
     private Object obj;
     
     public RunnableImplA(Object obj) {
      this.obj = obj;
     }
     
     public void run() {
      System.out.println("run on RunnableImplA");
      synchronized (obj) {
       System.out.println("obj to wait on RunnableImplA");
       try {
        obj.wait();
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
       System.out.println("obj continue to run on RunnableImplA");
      }
     }
    }
     
    class RunnableImplB implements Runnable {
     
     private Object obj;
     
     public RunnableImplB(Object obj) {
      this.obj = obj;
     }
     
     public void run() {
      System.out.println("run on RunnableImplB");
      System.out.println("  3 ...");
      try {
       Thread.sleep(3000);
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
      synchronized (obj) {
       System.out.println("notify obj on RunnableImplB");
       obj.notify();
      }
     }
    }
     
    class RunnableImplC implements Runnable {
     
     private Object obj;
     
     public RunnableImplC(Object obj) {
      this.obj = obj;
     }
     
     public void run() {
      System.out.println("run on RunnableImplC");
      System.out.println("  3 ...");
      try {
       Thread.sleep(3000);
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
      synchronized (obj) {
       System.out.println("notifyAll obj on RunnableImplC");
       obj.notifyAll();
      }
     }
    }
    
    결과:obj.notify()를 한 번 만 호출 합 니 다.스 레 드 t1 또는 t2 중 하 나 는 깨 어 나 기 를 기다 리 고 있 습 니 다.프로그램 이 종료 되 지 않 습 니 다.
    run on RunnableImplA
    obj to wait on RunnableImplA
    run on RunnableImplA
    obj to wait on RunnableImplA
    run on RunnableImplB
    잠 3 초...
    notify obj on RunnableImplB
    obj continue to run on RunnableImplA
    t3 주 를 떨 어 뜨리 고 t4 스 레 드 를 시작 합 니 다.obj.notifyAll()방법 호출
    
    public class TestNotifyNotifyAll { 
     private static Object obj = new Object();
      public static void main(String[] args) {
      
      //   RunnableImplA wait()        
      Thread t1 = new Thread(new RunnableImplA(obj));
      Thread t2 = new Thread(new RunnableImplA(obj));
      t1.start();
      t2.start();
      
    //  //RunnableImplB notify()
    //  Thread t3 = new Thread(new RunnableImplB(obj));
    //  t3.start();
      
      
      //RunnableImplC notifyAll()
      Thread t4 = new Thread(new RunnableImplC(obj));
      t4.start();
     } 
    }
    결과:t1,t2 스 레 드 모두 실행 가능
    run on RunnableImplA
    obj to wait on RunnableImplA
    run on RunnableImplA
    obj to wait on RunnableImplA
    run on RunnableImplC
    잠 3 초...
    notifyAll obj on RunnableImplC
    obj continue to run on RunnableImplA
    obj continue to run on RunnableImplA
    자바 의 notify()와 notify All()의 사용 차이 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 notify()와 notify All()내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기