2014-07-11 18 views
3

내 자바 프로그램에 두 개의 스레드가 있는데, 하나는 주 스레드이고 다른 스레드는 주 스레드에서 생성 된 스레드 A입니다. 이제는 주 스레드가 스레드 A를 시작하고 스레드 A가 실행 방법에서 코드의 일부를 실행하고 스레드 A가 자체를 일시 중단해야 할 때까지 기다려야합니다. 메인 쓰레드는 실행을 시작하고, 몇 줄의 코드를 실행 한 다음 다시 쓰레드 A가 멈춘 곳에서 시작해야하고, 그 반대도 마찬가지입니다. 이것은 n 번 반복해야합니다. 내가는 belows로 노력하고 있어요 :자바에서 두 스레드 동기화

public class ThreadA implements Runnable { 
    boolean suspended = false; 
    boolean stopped = false; 
    synchronized void stop() { 
     stopped = true; 
     suspended = false; 
     notify(); 
    } 
    synchronized void suspend() { 
     suspended = true; 
    } 
    synchronized void resume() { 
     suspended = false; 
     notify(); 
    } 
    void job() throws InterruptedException { 
     for (int i = 0; i < 5; i++) 
      synchronized (this) { 
       System.out.println("performing job."); 
       suspend(); 
       while (suspended) { 
        notify(); 
        suspended = false; 
       } 
      } 
    } 
    @Override 
    public void run() { 
     try { 
      job(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

MainThread :

public class MainThread { 
    public static void main(String[] args) throws InterruptedException { 
     ThreadA a1=new ThreadA(); 
     Thread t1=new Thread(a1); 
     synchronized (t1) { 
      t1.start(); 
      for (int i = 0; i < 5; i++) { 
       t1.wait(); 
       System.out.println("perform some action"); 
       a1.resume(); 
      } 

     } 
    } 
} 

예상 출력 :

performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 

실제 출력 :

이 클래스 스레드

작업 방법에서 notify() 신호를 발행 한 경우에도 전체 for 루프가 스레드 A에서 실행되는 이유를 알 수 없습니다.

+3

더 단순화? 당신은 단지 하나의 쓰레드로 똑같이 할 수있다. – JohnnyAW

+3

Sidenote : 서로 다른 객체에있는 두 개의 쓰레드를 동기화 시키므로,'synchronized' 문은 꽤 쓸모가 없다. – Thomas

+0

완전 무작위로 기대하십니까? 또는 작업 - 작업 - 작업 - 단계에서? –

답변

1

여기 당신이 2 개 스레드를 실행하는 이유, 즉 잇달아 실행하지 교육의 경우 방법

public class TwoThread { 

    public static void main(String[] args) throws InterruptedException { 
     ThreadA a1 = new ThreadA(); 
     Thread t1 = new Thread(a1); 

     synchronized (a1) { 
      t1.start(); 
      for (int i = 0; i < 5; i++) { 
       a1.wait(); 
       System.out.println("perform some action " + i); 
       a1.notify(); 
      } 

     } 
    } 
} 

public class ThreadA implements Runnable { 
    boolean suspended = false; 
    boolean stopped = false; 

    void job() throws InterruptedException { 
     for (int i = 0; i < 5; i++) 
      synchronized (this) { 
       System.out.println("performing job. " + i); 
       notify(); 
       wait(); 
      } 
    } 

    public void run() { 
     try { 
      job(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 

} 
+0

thanks @ mmc18 나는 이전에 위와 같은 시도를 했었지만 thread lock을 가지고있는 어리석은 실수 때문에 왜 알리지 않고 작동하지 않는지를 알아낼 수 없었다. 수정을 시도한 후 이제 사용자 정의 일시 중단 및 중지 방법이 필요하지 않습니다. 감사. 당신의 대답을 수락하십시오. –

+0

나는 다시 몇 가지 문제에 부딪혔다. 나를 도와주세요. 내가 실행중인 작업은 데몬 스레드에서 열립니다. 그래서 스레드 t1과 느슨한 객체 잠금을 시작할 때마다 잠금이 데몬 스레드에 의해 획득됩니다. 데몬 스레드는 일부 스레드를 처리하고 거기에서부터 느슨한 잠금으로 내 스레드를 기다리고 기다리고 있습니다. 무한정. 이것에 대한 가능한 해결책은 무엇입니까? –

2

여기에 두 가지 버그가 있습니다.

첫 번째는 다른 개체를 동기화하고 알리는 것입니다. 이 수정 된 주 시도, 동기화 된 (t1) 동기화 된 (a1) 및 t1.wait() a1.wait() 변경되었습니다.

public static void main(String[] args) throws InterruptedException { 
    ThreadA a1=new ThreadA(); 
    Thread t1=new Thread(a1); 

    synchronized (a1) { // CHANGED FROM t1 to a1 
     t1.start(); 
     for (int i = 0; i < 5; i++) { 
      a1.wait(); // CHANGED FROM t1 to a1 
      System.out.println("perform some action"); 
      a1.resume(); 
     } 

    } 
} 

두 번째 버그는 job() 메소드에 있으며 notify()는 호출하지만 wait()는 호출하지 않습니다. 내 테스트 실행에서

void job() throws InterruptedException { 
    for (int i = 0; i < 5; i++) 
     synchronized (this) { 
      System.out.println("performing job."); 
      suspend(); 
      while (suspended) { 
       notify(); 
       suspended = false; 
       wait(); // ADDED 
      } 
     } 
} 

출력은

performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 
performing job. 
perform some action 
+0

이 코드를 사용해 보셨습니까? 나는 그것이 작동하지 않는다는 것을 시험했다 –

+0

@ mmc18, 그렇습니다. 그러나 당신은 제가 누락 된 것을 깨닫게했습니다. 나는 위로 올라가는 코멘트에서 언급 한 다른 버그를 고쳤지만이 대답을 넣지는 않았다. 이것을 지적 해 주셔서 고맙습니다. 저는 답을 고쳤습니다. –

+0

@ChrisK가 답을 시도했지만 제대로 작동합니다. 바보 같은 실수가 스레드 개체를 잡고 있었다. 바보. –

0

다른 그 일을하는 동안 하나의 대기 스레드 경우 다중 스레드를 동기화하는 작은 이유가 있습니다 : 여기에 고정 된 버전입니다. 집행자를 사용하여 적은 작업으로 같은 결과를 얻을 수 있고 여전히 스레드로 놀고 있다는 느낌을받을 수 있습니다.

public class Main { 

    public static void main(String[] args) { 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     for(int i = 0; i<5;i++) { 
      executor.submit(new PrintTask("performing job.")); 
      executor.submit(new PrintTask("perform some action")); 
     } 
     executor.shutdown(); 
    } 

    private static class PrintTask implements Runnable { 
     private String string; 

     public PrintTask(String string) { 
      this.string = string; 
     } 

     @Override 
     public void run() { 
      System.out.println(string); 
     } 
    } 

}