Java에서 Thread.join()은 쓰레드의 종료를 기다릴 때 사용합니다.

멀티 스레드를 사용할 때, join()으로 대기하는 방법에 대해서 알아보겠습니다.

1. Thread.join() 함수

Thread.join() 함수는 스레드가 종료될 때까지 대기하며, 종료 후 다음 코드가 실행됩니다.

아래 예제처럼 start()로 스레드가 실행된 후에, join()을 호출하면 완료될 때까지 메인 스레드는 대기를 합니다.

  • Thread.start() : 스레드 실행 (스레드가 생성되도 start()가 호출되지 않으면 동작하지 않음)
  • thread1.join() : thread1의 작업이 완료될 때까지 대기, InterruptedException가 발생할 수 있으니 try-catch로 예외처리 필요
public class Example {

    public static void main(String[] args) {

        Thread thread1 = new Thread(() -> {
            System.out.println("Thread 1 is running");
            try {
                Thread.sleep(2000); // 2초 동안 스레드1 sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1 is done");
        });

        // 스레드1 시작
        thread1.start();

        try {
            // 스레드1 종료 대기
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread is done");
    }
}

Output:

Thread 1 is running
Thread 1 is done
Main thread is done

2. 첫번째 스레드 종료 대기 후, 다른 스레드 실행

두개의 스레드 Thread1과 Thread2가 있을 때, 두개를 동시에 실행시키지 않고 아래와 같이 순차적으로 실행시킬 때 join()을 이용할 수 있습니다.

  • Thread1 실행
  • Thread1 완료 후, Thread2 실행

아래 예제를 보시면, join()으로 thread1이 완료될 때까지 기다린 후 thread2를 실행시킵니다.

public class Example {

    public static void main(String[] args) {

        Thread thread1 = new Thread(() -> {
            System.out.println("Thread 1 is running");
            try {
                Thread.sleep(2000); // 2초 동안 스레드1 sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1 is done");
        });

        Thread thread2 = new Thread(() -> {
            System.out.println("Thread 2 is running");
            try {
                Thread.sleep(3000); // 3초 동안 스레드2 sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 2 is done");
        });

        // 스레드1 시작
        thread1.start();

        try {
            // 스레드1이 종료될 때까지 기다림
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 스레드2 시작
        thread2.start();

        System.out.println("Main thread is done");
    }
}

Output:

Thread 1 is running
Thread 1 is done
Main thread is done
Thread 2 is running
Thread 2 is done

3. 2개 스레드 동시 실행 및 종료 대기

이번엔 2개의 스레드를 동시에 실행시키고, 메인 스레드에서는 join() 두개의 스레드가 끝날 때까지 기다립니다.

  • thread1과 thread2의 start() 함수를 동시에 호출(스케줄링 상황에 따라서 누가 먼저 실행될 지 알 수 없음)
  • 스레드 실행 후, join()으로 두개 스레드 동시 대기
public class Example {

    public static void main(String[] args) {

        Thread thread1 = new Thread(() -> {
            System.out.println("Thread 1 is running");
            try {
                Thread.sleep(2000); // 2초 동안 스레드1 sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1 is done");
        });

        Thread thread2 = new Thread(() -> {
            System.out.println("Thread 2 is running");
            try {
                Thread.sleep(3000); // 3초 동안 스레드2 sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 2 is done");
        });

        // 스레드 1, 2 시작
        thread1.start();
        thread2.start();

        try {
            // 스레드 1, 2가 종료될 때까지 기다림
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread is done");
    }
}

Output:

Thread 2 is running
Thread 1 is running
Thread 1 is done
Thread 2 is done
Main thread is done