2
를이 코드를 실행하면

, 그것은 다음과 같은 출력이 표시됩니다 : 1 2 : 1 인가다시 시작 스레드를 일시 중단 자바

One : 15 Two : 15 One : 14 Two : 14 Two : 13 One : 13 Two : 12 One : 12 One : 11 Two : 11 Thread 1 suspended Two : 10 Two : 9 Two : 8 Two : 7 Two : 6 Thread 1 resumed Thread 2 suspended Thread 2 resumed

이 출력은 하나입니다 끝날 때까지 계속하지 않습니다 myresume NewThread1 클래스의 메서드가 실행되지 않았습니까? 이 이유는 무엇입니까? NewThread1의 코드

class NewThread1 implements Runnable{ 
String name; 
Thread t; 
boolean suspendFlag; 

NewThread1(String threadname){ 
    name = threadname; 
    t = new Thread(this, name); 
    suspendFlag = false; 
    t.start(); 
} 

@Override 
public void run(){ 
    try{ 
     for(int i=15; i>0; i--){ 
      System.out.println(name+ " : " +i); 
      Thread.sleep(200); 
       synchronized(this){ 
        while(suspendFlag){ 
         wait(); 
        } 
       } 
     } 
    }catch(InterruptedException e){ 
     System.out.println("New thread1 Interrupted"); 
    } 
} 
synchronized void myresume(){ 
    suspendFlag = false; 
} 
void mysuspend(){ 
    suspendFlag = true; 
} 
}   

다음입니다 :

는 다음 NewThread1의 코드 중단

public class Suspend_ResumeThreads { 
public static void main(String args[]){ 
    NewThread1 ob1 = new NewThread1("One "); 
    NewThread1 ob2 = new NewThread1("Two "); 

    try{ 
     Thread.sleep(1000); 
     ob1.mysuspend(); 
     System.out.println("Thread 1 suspended"); 
     Thread.sleep(1000); 
     ob1.myresume(); 
     System.out.println("Thread 1 resumed"); 

     ob2.mysuspend(); 
     System.out.println("Thread 2 suspended"); 
     Thread.sleep(1000); 
     ob2.myresume(); 
     System.out.println("Thread 2 resumed"); 

    }catch(InterruptedException e){ 
     System.out.println("Main Interrupted"); 
    } 

    try{ 
     ob1.t.join(); 
     ob2.t.join(); 
    }catch(InterruptedException e){ 
     System.out.println("Main interrupeted in join()"); 
    } 
System.out.println("Main exiting..");  
} 
} 
+1

같은 객체에'.nitify()'를 호출하여 그 객체에'.wait()'에 걸린 스레드를 깨우지 않으면 안됩니다. –

+0

알림/대기를 사용하면 항상 상태 변경과 연결되어야합니다. Notify()는 대기중인 것이없고 손실 될 수 있고 wait()가 가짜로 깨울 수있을 때 발생할 수 있습니다. –

+0

또한'suspendFlag'를 휘발성으로 표시하십시오. 또는'synchronized' 섹션에서 변경하십시오. – talex

답변

5

사용 notifyAll을 (main() 메소드가 정의된다)는 wait() :

를 넣어

myresume() 기능이 있습니다. 그러나 항상이 통지를 잃어 버릴 준비를하십시오. 특히 현재 대기중인 스레드가없는 경우에도 성공합니다.

같은 개체에 대한 당신 synchronize/wait/notify해야합니다. 일반적인 오류는 this에서 동기화하고 익명 내부 클래스의 컨텍스트에서 this이 다른 것일 수 있다는 것을 인식하지 못합니다. 코드를 리팩터링 할 때 변경 될 수 있습니다. 이러한 프로그래밍 및 리팩터링 오류를 방지하려면 Object lock = new Object(); 어딘가에 항상 synchronize(lock) ... lock.wait(); ... lock.notifyAll();을 사용하는 것이 가장 좋습니다. 당신이 suspendFlagvolatile을하지 않는

, (이 volatile가없는 경우, 스레드가 CPU의 캐시에 로컬 복사본을 유지할 수 있습니다) 다른 스레드가이 분야의 다른 값을 볼 수있는 기회도있다. 따라서 mysuspend도 동기화하는 것이 좋습니다.

경우에 따라 java.util.concurrent.locks.Lockjava.util.concurrent.Semaphore과 같이 고급 동기화로 전환해야 할 수 있습니다.