🧵 자바 스레드와 콜스택 완벽 정리
✅ 자바에서 스레드를 만드는 두 가지 방법
자바에서 멀티스레드를 구현하는 방법은 대표적으로 두 가지가 있다:
1. Thread 클래스 상속
class MyThread extends Thread {
public void run() {
System.out.println("스레드 실행 중");
}
}
- Thread 클래스 자체를 상속하고 run() 메서드를 오버라이딩한다
- 단점: 자바는 단일 상속만 가능하기 때문에, 다른 클래스를 동시에 상속받을 수 없다
2. Runnable 인터페이스 구현
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable 실행 중");
}
}
// 실행
Thread t = new Thread(new MyRunnable());
t.start();
- Runnable은 실행 로직만 정의하고, Thread 클래스에 위임하여 실행함
- 훨씬 유연하고 실무에서 훨씬 많이 사용됨
✅ start()와 run()의 차이
메서드 의미 실행 결과
run() | 그냥 메서드 호출 | 새로운 스레드 없이 현재 스레드에서 실행 |
start() | JVM에게 새 스레드를 만들라고 요청 | 진짜로 새로운 스레드가 생성됨 |
예시
Runnable r = new MyRunnable();
r.run(); // ❌ main 스레드에서 실행됨 (멀티스레드 아님)
Thread t = new Thread(r);
t.start(); // ✅ 별도의 스레드가 생성됨
start()는 "감독이 액션!"을 외쳐 새로운 배우(스레드)가 등장하는 것이고,
run()은 대본만 혼자 읽는 느낌이다 (멀티스레드 아님).
✅ Runnable에는 왜 start()가 없을까?
Runnable은 단순히 "할 일(run())을 정의한 인터페이스"일 뿐, 스레드 기능은 없다.
실제로 스레드를 생성하려면 Thread 클래스의 start() 메서드를 사용해야 하므로, 아래처럼 작성해야 한다:
Runnable task = new MyRunnable();
Thread t = new Thread(task);
t.start(); // 이걸로만 진짜 스레드 실행 가능!
✅ run()은 콜스택과 무슨 관계가 있을까?
run()도 일반적인 메서드이기 때문에 호출되면 콜스택에 올라간다.
하지만 스레드마다 콜스택을 따로 하나씩 가지기 때문에 실행 방식에 따라 콜스택 구조가 달라진다.
run() 직접 호출 시
- 같은 스레드(main) 안에서 실행됨
- 콜스택: main() → run() (같은 스택)
start()로 실행 시
- JVM이 새로운 스레드와 새로운 콜스택을 만들어줌
- 콜스택1: main()
- 콜스택2: run() (새로운 스레드에서)
✅ 스레드당 콜스택은 하나
모든 자바 스레드는 고유한 콜스택 하나만을 가지고 있다.
콜스택은 스레드가 실행 중 호출하는 모든 메서드를 추적하고 관리하는 공간이다.
예를 들어 다음과 같이 여러 스레드를 만들면:
public static void main(String[] args) {
new Thread(() -> sayHello()).start();
new Thread(() -> sayBye()).start();
}
- main()은 main 스레드의 콜스택에서 실행
- sayHello()는 Thread-0의 콜스택에서 실행
- sayBye()는 Thread-1의 콜스택에서 실행
스레드가 많아질수록 각각 독립적인 콜스택을 가지고 동작하게 된다.
💬 마무리 요약
- 자바에서 스레드는 Thread 상속 또는 Runnable 구현으로 만들 수 있다
- 실행은 반드시 start()로 해야 새로운 스레드에서 run()이 동작한다
- run()만 호출하면 현재 스레드에서 그냥 메서드처럼 실행될 뿐이다
- 모든 스레드는 자신의 콜스택 하나를 가지고 있으며, 메서드 실행 흐름은 그 스택 안에서 관리된다
'개발 > Java' 카테고리의 다른 글
Java 버전에 따른 GC (0) | 2025.05.27 |
---|---|
불변 객체(immutable object)의 개념과 사용 (0) | 2025.05.24 |
직렬화 (0) | 2025.05.22 |
원시타입(Primitive type)과 참조타입(Reference type) (0) | 2025.05.22 |
Java GC(Garbage Collector) (1) | 2024.12.04 |