2013-06-06 4 views
4

스레드의 순서를 만들어야합니다. 그들은 다음과 같은 순서로 시작해야합니다join()과 wait() 스레드를 사용하여 자바

A then B then C and finally D.

D는 C가 다음 B를 완료 할 수 있습니다 후 완료되면 다음 join() 스레드 또는 wait()을 사용하는 것이 좋습니다 무엇을이 상황에서

A.

? 그리고 왜?

스레드가 시작되고 메시지가 Hello I'm thread a/b/c/d으로 인쇄되어야하며 완료되면 I'm finished a/b/c/d을 인쇄해야합니다.

+0

Th 두 가지가 실제로 관련이 없습니다. –

+3

스레드의 실행을 일시 중지하려고합니다. 스레드에 대한 Oracle Java 자습서를 참조하십시오. http://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html – AurA

+0

@BrianRoach가 나에게 설명을 해줄 수 있습니까? 그? 이 경우에는 무엇을 사용해야합니까? – njamanjam

답변

5

당신이 (즉, 마무리의 실행을) 완료 ''다른 스레드를 기다리고 있기 때문에, join()는 더 나은 선택이 될 것입니다.

join()의 javadoc은 간단하게 : 이 스레드가 죽을 때까지 기다립니다.

메커니즘은 비교적 간단하다 :

 @Override 
     public void run() { 
      System.out.println("Hello I'm thread " + getName()); 
      if (otherThread != null) { 
       while (otherThread.isAlive()) { 
        try { 
         otherThread.join(); 
        } catch (InterruptedException e) { 
         // ignore 
        } 
       } 
      } 
      System.out.println("I'm finished " + getName()); 
     } 

설명하기 : 당신은 otherThread에 대한 참조가 필요합니다. 따라서 ab을 말하고, bc을 말하고, cd을 말하고 dotherThread (null이 아닙니다)을 의미하지 않습니다.

otherThread.join()은 다른 스레드가 완료되기를 기다립니다. join()InterruptedException을 던질 수 있기 때문에 루프에 싸여 있습니다 (실제로는 거의 발생하지 않음).

호프 행운을 빕니다.

+0

otherThread.join() 자체가 otherthread.isAlive()를 확인할 것입니다.이 코드는 중복되거나 필요하지 않습니다 - http://grepcode.com/file /repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Thread.java#Thread.join%28long%29 – Naren

+2

@Naren은 [Javadoc]에서 [guarded blocks]에 대해 언급했습니다. https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html) -'참고 : 대기중인 조건을 테스트하는 루프 내에서 wait를 호출하십시오. 기다리는 특정 조건에 대한 인터럽트가 아니라고 가정하거나 조건이 여전히 참이라고 가정하지 마십시오. '나는 그의 구현이 옳다고 생각한다. –

+0

아!, 그렇게 ... 감사합니다 @yadav_vi, 도움이되었습니다 – Naren

3

join() 메서드는 스레드 실행 완료를 기다리는 데 사용됩니다. 스레드 인스턴스의 join() 메서드는 다른 스레드가 끝날 때까지 스레드가 실행되지 않도록 다른 스레드의 실행이 끝날 때까지 스레드의 실행 시작을 "조인"하는 데 사용할 수 있습니다. 스레드 인스턴스에서 join()이 호출되면 현재 실행중인 스레드는 스레드 인스턴스가 실행을 마칠 때까지 차단됩니다.

An example of join()

wait() 방법은 개체에 대해 송신하는 통지를 기다리는 사용된다. 두 가지 조건은 매우 독특합니다.

An example and more explanation of wait()

+0

더 나은 join() 또는 wait()가 무엇이라고 생각합니까? – njamanjam

+1

@njamanjam 어느 쪽도 "더 나을 것"이 아닙니다. 이 둘은 실제로 비교할 수 없습니다. –

+0

그래, 당신이 질문에서주는 예제가 가장 이상한 것입니다 ... – Joetjah

9

joinwait은 매우 다른 일을하며 실제로 관련이 없으며, 제공 한 예가 실제로 매우 이상하다는 것을 염두에두면 선택 사항 중 하나가 잠재적으로 사용자가 찾고있는 것일 수 있습니다. .

join이 더 쉬운 선택 일 수 있습니다. join을 호출하는 스레드는 다른 스레드가 실행을 마칠 때까지 대기합니다. 따라서이 경우 각 스레드는 스레드에 대한 참조를 보유해야하며 "I 'm finished"인쇄 전에 join을 호출합니다.

class JoiningThread extends Thread { 
    // NOTE: UNTESTED! 

    private String name; 
    private Thread nextThread; 

    public JoiningThread(String name) { 
     this(name, null); 
    } 

    public JoiningThread(String name, Thread other) { 
     this.name = name; 
     this.nextThread = other; 
    } 

    public String getName() { 
     return name; 
    } 

    @Override 
    public void run() { 
     System.out.println("Hello I'm thread ".concat(getName())); 
     if (nextThread != null) { 
      while(nextThread.isAlive()) { 
       try { 
        nextThread.join(); 
       } catch (InterruptedException e) { 
        // ignore this 
       } 
      } 
     } 
     System.out.println("I'm finished ".concat(getName())); 
    } 
} 

을 그리고 주요 방법이 될 수있다 : 그래서 클래스는 다음과 같을 수

wait이 무엇
public static void main(String[] args) { 
    Thread d = WaitingThread("d"); 
    Thread c = WaitingThread("c", d); 
    Thread b = WaitingThread("b", c); 
    Thread a = WaitingThread("a", b); 

    a.start(); 
    b.start(); 
    c.start(); 
    d.start(); 

    try { 
     a.join(); 
    } catch (InterruptedException e) {} 
} 

notify 또는 notifyAll가 호출 될 때까지 스레드의 실행을 중지합니다. 따라서 wait으로이 아이디어를 구현하려면 에 대한 참조를 보유하기 위해 각 스레드가 앞에 있어야합니다. 이 전략은 run 메서드를 wait으로 호출 한 다음 실행이 끝난 이전 스레드 notify을 호출하는 것입니다. 그래서 클래스는 다음과 같이 보일 수 있습니다 :

class WaitingThread extends Thread { 
    // NOTE: UNTESTED! 

    private Thread previousThread; 
    private String name; 

    public WaitingThread(String name) { 
     this(name, null); 
    } 

    public WaitingThread(String name, Thread other) { 
     this.name = name; 
     this.previousThread = other; 
    } 

    public String getName() { 
     return name; 
    } 

    @Override 
    public void run() { 
     System.out.println("Hello I'm thread ".concat(getName())); 
     // Do other things if required 

     // Wait to be woken up 
     while(true) { 
      synchronized(this) { 
       try { 
        wait(); 
        break; 
       } catch (InterruptedException e) { 
        // ignore this 
       } 
      } 
     } 

     System.out.println("I'm finished ".concat(getName())); 

     // Wake up the previous thread 
     if (previousThread != null) { 
      synchronized(previousThread) { 
       previousThread.notify(); 
      } 
     } 
    } 
} 

할 수있는 메인 스레드에서 모든 것을 최대를 설정 main 방법 :

public static void main(String[] args) { 
    Thread a = WaitingThread("a"); 
    Thread b = WaitingThread("b", a); 
    Thread c = WaitingThread("c", b); 
    Thread d = WaitingThread("d", c); 

    a.start(); 
    b.start(); 
    c.start(); 
    d.start(); 

    while(true) { 
     // wake up d once it goes to sleep 
     if (d.isAlive()) { 
      d.notify(); 
     } 
    } 
} 
1

내가 이런 식으로 할 것

public class Test1 extends Thread { 
    static Object lock = new Object(); 
    static int n; 
    int i; 
    String name; 

    Test1(String name, int i) { 
     this.name = name; 
     this.i = i; 
    } 

    @Override 
    public void run() { 
    try { 
     synchronized (lock) { 
      while (i != n) { 
       lock.wait(); 
      } 
      System.out.println(name + " started"); 
      n++; 
      lock.notifyAll(); 
     } 
     synchronized (lock) { 
      while (i != n - 4) { 
       lock.wait(); 
      } 
      System.out.println(name + " finished"); 
      n++; 
      lock.notifyAll(); 
     } 
    } catch (InterruptedException e) { 
    } 
    } 

    public static void main(String[] args) throws Exception { 
     new Test1("a", 0).start(); 
     new Test1("b", 1).start(); 
     new Test1("c", 2).start(); 
     new Test1("d", 3).start(); 
    } 
} 

출력

a started 
b started 
c started 
d started 
a finished 
b finished 
c finished 
d finished 
관련 문제