2016-09-10 2 views
4

wait 및 notify 메소드의 개념을 익히기 위해 간단한 Java 예제를 작성했습니다.if 조건 내에서 Java notify() 호출

notify()을 호출하면 주 스레드가 합계를 인쇄합니다.

MyThread 클래스

public class MyThread extends Thread { 
    public int times = 0; 

    @Override 
    public void run() { 

     synchronized (this) { 
      try { 
       for (int i = 0; i < 10; i++) { 
        times += 1; 
        Thread.sleep(500); 
        if (i == 5) { 
         this.notify(); 
        } 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

메인 클래스

public class Main { 

    public static void main(String[] args) { 

     MyThread t = new MyThread(); 
     synchronized (t) { 
      t.start(); 
      try { 
       t.wait(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      System.out.println(t.times); 
     } 
    } 
} 

예상 결과

5하지만 대신 10을 얻었다.

그래도 호출 될 때 notify(), 메인 스레드가 웨이크 업하고 10 배의 값을 업데이트합니다 for 루프를 완료까지 5. 그런 다음 run()가 계속 제공해야 System.out.println(t.times)를 실행하는 것이 무엇인지 잘,

도움이 매우 감사합니다.

+5

'notify '는 잠금을 해제하지 않습니다. – tkausl

+0

이 문제에 대해 더 자세히 알려 주실 수 있습니까? – Mazen

+2

[자바에서 wait() 및 notify()를 사용하는 간단한 시나리오] (http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java)의 가능한 복제본 –

답변

5

동기화 된 블록은 상호 배제를 의미합니다. 어느 순간이든 하나의 스레드 만 잠금을 유지하고 동기화 된 블록 내에서 코드를 실행할 수 있습니다. 이 규칙은 동일한 잠금에 의해 보호되는 모든 블록으로 퍼집니다.

같은 잠금을 사용하는 두 개의 블록이 있으므로 기본 스레드이거나이 블록 중 하나에서 코드를 실행할 수있는 MyThread이고 다른 스레드는 대기해야합니다. 따라서 다음과 같은 시나리오가 있습니다.

  1. 주 스레드가 잠금을 획득합니다.
  2. 주 스레드가 두 번째 스레드를 시작합니다.
  3. 두 번째 스레드는 동기화 된 블록에 도달하지만 잠금이 주 스레드에 의해 보류 중이므로 입력 할 수 없습니다.
  4. 메인 스레드는 wait()을 호출합니다. 이 호출은 잠금을 해제하고 주 스레드를 WAITING 상태로 만듭니다.
  5. 이제 두 번째 스레드가 잠금을 획득하고 동기화 된 블록을 시작할 수 있습니다.
  6. 두 번째 스레드는 5로 계산되고 notify()을 호출합니다. 이 호출은 잠금을 해제하지 않고 잠금을 다시 획득 할 수있게되는 즉시 진행할 수있는 주 스레드에 알립니다.
  7. 메인 스레드는 깨어 나지 만 잠금을 다시 획득 할 수 없으므로 진행할 수 없습니다 (여전히 두 번째 스레드가 대기 중입니다). 한 번에 같은 잠금에 의해 보호되는 동기화 된 블록 내에서 두 개의 스레드가 활성화 될 수 없다는 것을 기억하십시오. 이제 두 번째 스레드가 여전히 활성 상태이므로 주 스레드는 계속 대기해야합니다.
  8. 두 번째 스레드는 계속 카운팅하고 times을 10으로 설정하고 결국 동기화 된 블록을 떠나 잠금을 해제합니다.
  9. 메인 스레드가 잠금을 다시 획득하므로 println으로 진행할 수 있습니다. 그러나 이번에는 times이 이미 10입니다.

당신도 결과가 두 번째가 완료되면 메인 쓰레드는 진행을 할 수있는 동일한 –되기 때문에 도움이되지 않습니다 join() 사용.

public class MyThread extends Thread { 
    public volatile int times = 0; 

    @Override 
    public void run() { 
     try { 
      for (int i = 0; i < 10; i++) { 
       times += 1; 
       Thread.sleep(500); 
       if (i == 5) { 
        synchronized(this) { 
         this.notify(); 
        } 
       } 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

times을하는 것을 잊지 마세요 : 두 번째 스레드가 5 안타 메인 쓰레드가 즉시 실행을 계속하려면

, 당신은 잠금을 획득하고 해당 이벤트 후 즉시 공개해야 휘발성, 그렇지 않으면 JVM은 메인 스레드에서 실제 값을 볼 수 있다고 보장하지 않습니다.

또한이 방법으로 기본 스레드가 인쇄되는 것을 보장하지 않는다는 것을 이해해야합니다. println 호출에 도달 할 때까지 두 번째 스레드가 하나 또는 두 개 이상의 반복 작업을 수행하고, 5보다 큰 값을 보게됩니다 (모든 반복에서 sleep() 호출로 인해 불행하게도).

+0

그것은 매력처럼 작동하고 있습니다. 앤드류 감사합니다. 많이 감사합니다. – Mazen

+0

잘 설명했습니다. 다시 한번 감사드립니다. – Mazen