자바에서 스레드의 start() 메서드를 호출하면 새로운 실행 흐름이 시작되고, Java Virtual Machine(JVM)이 내부적으로 해당 스레드의 run() 메서드를 호출합니다. 반면 run() 메서드를 직접 호출하면 이는 일반적인 오버라이딩된 메서드 호출로 취급되어, 새로운 스레드가 생성되지 않은 채 현재 실행 중인 스레드(주로 main 스레드)의 컨텍스트 안에서 순차적으로 실행됩니다.
즉, run()을 직접 호출하면 멀티스레딩의 이점을 전혀 얻을 수 없으며, 코드가 단순히 일반 메서드처럼 동작하게 됩니다. 실제 멀티스레드 환경이 필요하다면 반드시 start()를 호출해야 합니다.
예제 코드
public class CallRunMethodTest extends Thread {
@Override
public void run() {
System.out.println("In the run() method: " + Thread.currentThread().getName());
for(int i = 0; i < 5 ; i++) {
System.out.println("i: " + i);
try {
Thread.sleep(300);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
public static void main(String[] args) {
CallRunMethodTest t1 = new CallRunMethodTest();
CallRunMethodTest t2 = new CallRunMethodTest();
t1.run(); // start() 대신 run() 메서드를 직접 호출
t2.run(); // start() 대신 run() 메서드를 직접 호출
}
}위 예제에서는 두 개의 스레드 객체(t1, t2)를 생성한 후, start() 메서드 대신 run() 메서드를 각각 직접 호출하고 있습니다.
실행 결과
In the run() method: main i: 0 i: 1 i: 2 i: 3 i: 4 In the run() method: main i: 0 i: 1 i: 2 i: 3 i: 4
결과 분석
실행 결과를 보면 스레드 이름이 main으로 출력되는 것을 확인할 수 있습니다. 이는 run() 메서드가 별도의 새로운 스레드에서 실행된 것이 아니라, main 스레드 안에서 일반 메서드처럼 순차적으로 실행되었음을 의미합니다.
start()와 run()의 핵심 차이
- start(): JVM이 새로운 호출 스택(call stack)을 생성하고, 그 안에서 run() 메서드를 비동기적으로 실행합니다. 진정한 멀티스레드 환경이 구성됩니다.
- run(): 단순한 메서드 호출이므로 새로운 호출 스택이 만들어지지 않고, 호출한 스레드(main)와 동일한 스택에서 동기적으로 실행됩니다.
또한 하나의 스레드 객체에 대해 start()는 한 번만 호출할 수 있으며, 두 번째 호출 시에는 IllegalThreadStateException이 발생합니다. 반면 run()은 일반 메서드이므로 여러 번 호출해도 예외가 발생하지 않습니다.
결론적으로, run()을 직접 호출하는 것이 적절한 경우는 사실상 없으며, 멀티스레드 처리가 필요하다면 항상 start() 메서드를 사용해야 합니다.