쓰레드를 공부하던 중 join의 동작이 궁금해졌다.
join은 Thread 객체를 한데 묶어놓는다. 그리고 join으로 묶인 Thread 객체들은 모든 동작(run 메소드에서 수행되는 코드)이 완료될 때까지 해당 Thread 객체를 실행(start())한 Thread의 수행을 멈추어둔다.
이게 말로 풀어 설명하려니 조금 힘이 든다. 아래에 코드를 보고 이해해보자.
import java.util.*;
public class ThreadStudy extends Thread {
int seq;
ThreadStudy(int seq) {
this.seq = seq;
}
public void run() {
List<Thread> list = new ArrayList<>();
System.out.println(this.seq + " thread start.");
try {
for (int i=0; i<5; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("쓰레드 안에 쓰레드!");
try{
Thread.sleep(1000);}
catch (InterruptedException e){}
}
});
list.add(t);
t.start();
}
for (int i = 0; i < 5; i++) {
Thread t = list.get(i);
try {
t.join();
} catch (Exception e) {
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(this.seq + " thread end.");
}
public static void main(String args[]) {
Thread thread = new Thread();
List<Thread> threadList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Thread t = new ThreadStudy(i + 1);
t.start();
threadList.add(t);
}
for (int i = 0; i < 10; i++) {
Thread t = threadList.get(i);
try {
t.join();
} catch (Exception e) {
}
}
System.out.println("main end.");
}
}
위에는 ThreadStudy라는 자바 클래스의 모든 코드이고, 아래에 핵심만 보자.
public void run() {
List<Thread> list = new ArrayList<>();
System.out.println(this.seq + " thread start.");
try {
for (int i=0; i<5; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("쓰레드 안에 쓰레드!");
try{
Thread.sleep(1000);}
catch (InterruptedException e){}
}
});
list.add(t);
t.start();
}
for (int i = 0; i < 5; i++) {
Thread t = list.get(i);
try {
t.join();
} catch (Exception e) {
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(this.seq + " thread end.");
}
보면 Thread의 run 메소드 안에 또다시 Thread를 선언하고, 또 그 쓰레드를 실행하고 있다.
좀 더 자세히 설명해보겠다. ThreadStudy 클래스의 main 메소드에서 쓰레드를 선언 및 실행(main Thread)하고 있고, 그 쓰레드 안에서 또 쓰레드를 선언 및 실행하는 중이다.
아래에서 위 코드를 실행시킨 결과를 확인해볼 수 있다.
1 thread start.
3 thread start.
2 thread start.
4 thread start.
5 thread start.
6 thread start.
7 thread start.
8 thread start.
9 thread start.
10 thread start.
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
쓰레드 안에 쓰레드!
2 thread end.
7 thread end.
1 thread end.
6 thread end.
10 thread end.
9 thread end.
4 thread end.
3 thread end.
8 thread end.
5 thread end.
main end.
Process finished with exit code 0
main 메소드 안에서 수행되어지는 쓰레드를 A, "쓰레드 안에 쓰레드!"를 출력하는 쓰레드를 B라 하겠다.
이 동작을 자세히 살펴보면 'main시작-모든A시작-모든B시작-모든Bjoin-모든B완료-모든Ajoin-모든A완료-main완료'이다.
댓글