
자바에서 프로그램을 실행하면 기본적으로 하나의 작업 흐름이 실행됩니다.
하지만 현실의 프로그램을 보면 대부분 여러 작업을 동시에 수행합니다.
예를 들어 음악 플레이어를 생각해보면
이 모든 작업이 동시에 이루어집니다.
이때 이러한 동시에 실행되는 작업 흐름을 처리하기 위해 사용하는 것이 바로 Thread(스레드) 입니다.
Thread(스레드) 는 하나의 프로그램 안에서 실행되는 작업의 흐름입니다.
조금 더 쉽게 말하면
하나의 프로그램 안에서 동시에 여러 작업을 수행할 수 있도록 만들어주는 실행 단위
라고 볼 수 있습니다.
구조를 간단하게 보면 다음과 같습니다.
Program (Process)
├ Thread 1
├ Thread 2
└ Thread 3
하나의 프로그램 안에 여러 개의 스레드가 존재할 수 있으며
이를 통해 멀티태스킹이 가능해집니다.
자바에서는 스레드를 만드는 방법이 크게 두 가지 있습니다.
가장 기본적인 방법은 Thread 클래스를 상속하는 것입니다.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("스레드 실행");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
여기서 중요한 점은 두 가지입니다.
run()
run()
스레드가 실제로 수행할 작업 코드를 작성하는 메서드입니다.
start()
스레드를 실제로 실행시키는 메서드입니다.
주의할 점이 하나 있습니다.
run() 직접 호출 ❌
start() 호출 ⭕
왜냐하면
run() → 일반 메서드 호출
start() → 새로운 스레드 생성 후 run() 실행
이기 때문입니다.
자바에서는 사실 Runnable 방식을 더 많이 사용합니다.
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable 스레드 실행");
}
}
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
이 방법을 사용하는 이유는 자바의 특징 때문입니다.
자바는 단일 상속만 지원합니다.
class A extends B
이렇게 하나의 클래스만 상속할 수 있습니다.
그래서
Thread 상속
을 사용하면 다른 클래스를 상속할 수 없습니다.
하지만
Runnable implements
을 사용하면 다른 클래스 상속도 가능하기 때문에
이 방식이 더 많이 사용됩니다.
스레드를 사용하다 보면 실행 순서를 제어해야 할 때가 있습니다.
이때 사용하는 메서드가 바로
join()
입니다.
예제를 보면 다음과 같습니다.
class MyThread extends Thread {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("Thread 실행");
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyThread t = new MyThread();
t.start();
t.join();
System.out.println("main 실행");
}
}
실행 결과
Thread 실행
Thread 실행
Thread 실행
Thread 실행
Thread 실행
main 실행
join() 의 의미는 다음과 같습니다.
해당 스레드가 종료될 때까지 현재 스레드를 기다리게 한다.
즉
t.join()
은
t 스레드 끝날 때까지 main 스레드 대기
라는 의미가 됩니다.
그래서 동기 처리 느낌을 낼 수 있습니다.
자바 프로그램을 실행하면 사실 이미 하나의 스레드가 존재합니다.
바로
main thread
입니다.
즉 프로그램 구조는 다음과 같습니다.
main thread
여기에
Thread.start()
를 실행하면
main thread
새로운 thread
두 개가 동시에 실행됩니다.
다음 코드를 보겠습니다.
Thread t = new Thread(() -> {
System.out.println("Thread 실행");
});
t.start();
System.out.println("main 실행");
실행 결과는 두 가지가 될 수 있습니다.
Thread 실행
main 실행
또는
main 실행
Thread 실행
왜냐하면 스레드 실행 순서는
CPU 스케줄러
가 결정하기 때문입니다.
따라서 멀티스레드 환경에서는 실행 순서가 보장되지 않습니다.
자바 스레드는
스레드를 이해하면
같은 개념을 이해하는 데 큰 도움이 됩니다.