JAVA 다 중 루틴 중 join()방법의 사용 방법

스 레 드 join()방법 을 토론 하 는 블 로 그 는 이미 매우 많 았 지만 며칠 전에 저 는 곤 혹 스 러 웠 지만 상세 한 설명 을 받 지 못 했 습 니 다.즉,시스템 에서 여러 스 레 드 를 실행 하고 있 을 때 join()은 도대체 어떤 스 레 드 를 멈 추 었 는 지 입 니 다.대부분의 블 로 거들 이 준 예 는 t.join()방법 으로 모든 스 레 드 를 멈 추고 t 의 실행 을 기다 리 는 것 처럼 보 입 니 다.물론 이것 도 제 가 다 중 스 레 드 의 여러 가지 방법 과 동기 화 개념 에 대해 잘 이해 하지 못 하기 때 문 입 니 다.다른 사람의 분석 과 자신의 실천 을 통 해 알 게 되 었 습 니 다.저 와 똑 같이 곤 혹 스 러 운 친구 들 을 도 울 수 있 기 를 바 랍 니 다.
먼저 결론 을 내 립 니 다.t.join()방법 은 메 인 스 레 드(또는 t.join()의 스 레 드 를 호출 하 는 것)를 대기 탱크 에 들 어가 t 스 레 드 가 실 행 된 후에 야 깨 울 수 있 습 니 다.같은 시각 에 운행 상태 에 있 는 다른 스 레 드 에 영향 을 주지 않 습 니 다.
다음은 분석 과정 이다.
이전에 join()방법 에 대해 서 는 t.join()의 t 를 우선 실행 할 수 있 고 t 가 실 행 된 후에 야 다른 스 레 드 를 실행 할 수 있다 는 것 만 알 고 있 었 습 니 다.스 레 드 간 의 병렬 실행 을 직렬 실행 으로 바 꿀 수 있 습 니 다.

package CSDN;
public class TestJoin {
 
 public static void main(String[] args) throws InterruptedException {
  // TODO Auto-generated method stub
  ThreadTest t1=new ThreadTest("A");
  ThreadTest t2=new ThreadTest("B");
  t1.start();
  t2.start();
 }
 
 
}
class ThreadTest extends Thread {
 private String name;
 public ThreadTest(String name){
  this.name=name;
 }
 public void run(){
  for(int i=1;i<=5;i++){
    System.out.println(name+"-"+i);
  }  
 }
}
실행 결과:
A-1
B-1
B-2
B-3
A-2
B-4
A-3
B-5
A-4
A-5
A 라인 과 B 라인 이 번갈아 실 행 된 것 을 알 수 있다.
그 중에서 join()방법 을 추가 한 후(뒤의 코드 는 ThreadTest 류 의 정 의 를 생략 합 니 다)

package CSDN;
public class TestJoin {
 
 public static void main(String[] args) throws InterruptedException {
  // TODO Auto-generated method stub
  ThreadTest t1=new ThreadTest("A");
  ThreadTest t2=new ThreadTest("B");
  t1.start();
  t1.join();
  t2.start();
 }
}
실행 결과:
A-1
A-2
A-3
A-4
A-5
B-1
B-2
B-3
B-4
B-5
분명히 t1.join()을 사용 한 후에 B 스 레 드 는 A 스 레 드 가 실 행 된 후에 야 실 행 될 수 있다.주의해 야 할 것 은 t1.join()은 t1.start()가 실 행 된 후에 실행 해 야 효과 가 있다 는 것 이다.또한 t1.join()이 t2.start()에 놓 인 후에 도 교체 집행 이 될 것 이다.그러나 효과 가 없 는 것 은 아니다.이 점 은 나 를 오랫동안 괴 롭 혔 고 다른 블 로 거들 에서 도 본 적 이 없다.
깊이 이해 하기 위해 서 는 먼저 join()의 소스 코드 를 살 펴 보 자.

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);            //join()   join(0)
    }
    /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
 
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
 
        if (millis == 0) {
            while (isAlive()) {
                wait(0);           //join(0)   wait(0), wait       notify
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
join()방법의 밑바닥 은 wait()방법 으로 이 루어 진 것 임 을 알 수 있다.이 를 통 해 알 수 있 듯 이 join 방법 은 동기 화 방법 이다.메 인 스 레 드 가 t1.join()방법 을 호출 할 때 메 인 스 레 드 는 t1 대상 의 자 물 쇠 를 먼저 얻 었 고 그 다음 에 들 어 가 는 방법 으로 t1 대상 의 wait()방법 을 호출 하여 메 인 스 레 드 를 t1 대상 의 대기 탱크 에 들 어 갔다.이때 A 스 레 드 는 실행 되 고 그 다음 t2.start()가 실행 되 지 않 았 기 때문에 B 스 레 드 도 아직 시작 되 지 않 았 다.A 라인 이 실 행 된 후에 메 인 라인 이 계속 실 행 됩 니 다.t2.start()에 도착 해 야 B 라인 이 실 행 됩 니 다.
그 밖 에 join()의 위치 와 역할 의 관계 에 대해 우 리 는 아래 의 예 로 분석 할 수 있다.

package CSDN;
 
public class TestJoin {
 
 public static void main(String[] args) throws InterruptedException {
  // TODO Auto-generated method stub
  System.out.println(Thread.currentThread().getName()+" start");
  ThreadTest t1=new ThreadTest("A");
  ThreadTest t2=new ThreadTest("B");
  ThreadTest t3=new ThreadTest("C");
  System.out.println("t1start");
  t1.start();
  System.out.println("t2start");
  t2.start();
  System.out.println("t3start");
  t3.start();
  System.out.println(Thread.currentThread().getName()+" end");
 } 
}
실행 결과
main start
t1start
t1end
t2start
t2end
t3start
t3end
A-1
A-2
main end
C-1
C-2
C-3
C-4
C-5
A-3
B-1
B-2
B-3
B-4
B-5
A-4
A-5
A,B,C 와 메 인 스 레 드 가 교체 운행 된다.join()가입 방법 후

package CSDN;
 
public class TestJoin {
 
 public static void main(String[] args) throws InterruptedException {
  // TODO Auto-generated method stub
  System.out.println(Thread.currentThread().getName()+" start");
  ThreadTest t1=new ThreadTest("A");
  ThreadTest t2=new ThreadTest("B");
  ThreadTest t3=new ThreadTest("C");
  System.out.println("t1start");
  t1.start();
  System.out.println("t1end");
  System.out.println("t2start");
  t2.start();
  System.out.println("t2end");
  t1.join();
  System.out.println("t3start");
  t3.start();
  System.out.println("t3end");
  System.out.println(Thread.currentThread().getName()+" end");
 } 
}
실행 결과:
main start
t1start
t1end
t2start
t2end
A-1
B-1
A-2
A-3
A-4
A-5
B-2
t3start
t3end
B-3
main end
B-4
B-5
C-1
C-2
C-3
C-4
C-5
여러 번 의 실험 을 통 해 알 수 있 듯 이 메 인 스 레 드 는 t1.join()방법 에서 멈 추고 A 스 레 드 가 실 행 된 후에 야 t3.start()를 실행 할 수 있 지만 B 스 레 드 의 실행 에 영향 을 주지 않 습 니 다.따라서 t.join()방법 은 메 인 스 레 드 를 대기 탱크 에 들 어가 게 하고 t 스 레 드 가 실 행 된 후에 야 깨 어 날 수 있다 는 결론 을 얻 을 수 있다.같은 시각 에 운행 상태 에 있 는 다른 스 레 드 에 영향 을 주지 않 습 니 다.
PS:join 소스 코드 에 서 는 wait 방법 만 호출 되 고 끝 날 때 notify 를 호출 하지 않 습 니 다.이 는 스 레 드 가 die 일 때 자신의 notify All 방법 을 자동 으로 호출 하여 모든 자원 과 자 물 쇠 를 방출 하기 때 문 입 니 다.
JAVA 다 중 스 레 드 에서 join()방법 을 사용 하 는 방법 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 JAVA 다 중 스 레 드 join()방법 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기