본문 바로가기
language/java

Thread와 Runnable 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

Thread와 Runnable 완벽 이해하기

이전 글에서:

  • 프로세스(Process)
  • 스레드(Thread)

의 개념을 배웠습니다.

이번에는 Java에서 실제로 스레드를 만드는 방법인:

Thread

Runnable

을 알아보겠습니다.

실무 면접에서도 정말 자주 나오는 주제입니다.

특히:

 
new Thread(...)
 

 
implements Runnable
 

의 차이,

그리고

 
run()
 

 
start()
 

의 차이는 반드시 이해해야 합니다.


대표 이미지

Thread와 Runnable
Thread와 Runnable Thread와 Runnable
 
 

 


1. Thread란?

Thread

JVM 내부의 실행 흐름 단위

입니다.


2. Java 프로그램 시작 시

사실 이미 Thread가 존재합니다.

 
public static void main(String[] args)
 

이 코드를 실행하는 것도

Main Thread
 

입니다.


3. 확인해 보기

 
public class Main {

    public static void main(String[] args) {

        System.out.println(
            Thread.currentThread().getName()
        );
    }
}
 

출력

main
 

4. Thread 직접 생성

가장 단순한 방법.

 
public class MyThread
        extends Thread {

    @Override
    public void run() {

        System.out.println("실행");
    }
}
 

5. 실행

 
MyThread thread = new MyThread();

thread.start();
 

6. 결과

실행
 

7. 그런데 여기서 의문

 
run()
 

을 만들었는데

실행은

 
start()
 

를 호출할까?


8. run() 역할

run()은

스레드가 실제 수행할 작업
 

입니다.


9. start() 역할

매우 중요.

새로운 스레드 생성 요청
 

입니다.


10. JVM 내부 흐름

 
thread.start();
 

새 Thread 생성
↓
OS 스케줄러 등록
↓
run() 호출
 

11. run() 직접 호출하면?

많이 틀리는 문제.

 
thread.run();
 

12. 결과

새 Thread 생성 안 됨.


13. 실제 동작

Main Thread
 ↓
run() 메서드 호출
 

일 뿐.


14. 예시

 
Thread t = new Thread(
    () -> {
        System.out.println(
            Thread.currentThread().getName()
        );
    }
);

t.run();
 

출력

main
 

15. start() 사용

 
t.start();
 

출력

Thread-0
 

16. 면접 단골

run()과 start() 차이?

run()
=
일반 메서드 호출

start()
=
새 Thread 생성 후 run() 실행
 

17. 그런데 Thread 상속은 문제 있음

예:

 
class MyThread
        extends Thread
 

Java는

단일 상속
 

만 가능.


18. 문제

이미 다른 클래스 상속 중이면?

 
class MyService
        extends BaseService
 

Thread 상속 불가.


19. 그래서 등장

Runnable


20. Runnable이란?

Runnable

실행할 작업만 정의하는 인터페이스

입니다.


21. 구조

 
public interface Runnable {

    void run();
}
 

22. 구현

 
public class MyTask
        implements Runnable {

    @Override
    public void run() {

        System.out.println("실행");
    }
}
 

23. 실행

 
Runnable task =
        new MyTask();

Thread thread =
        new Thread(task);

thread.start();
 

24. 실행 흐름

Thread
 ↓
Runnable.run()
 

25. 왜 분리했을까?

매우 중요.


26. 역할 분리

Thread

실행 주체
 

Runnable

실행할 작업
 

27. 객체지향적으로 더 좋음

작업
↓
실행
 

분리.


28. 실무는 Runnable 중심

대부분:

 
new Thread(...)
 

직접 잘 안 씀.


29. 예시

 
Runnable task =
    () -> {

        System.out.println(
            Thread.currentThread()
                  .getName()
        );
    };
 

30. Lambda 사용

Runnable은

 
@FunctionalInterface
 

라서

람다 가능.


31. 실무 스타일

 
Thread thread =
    new Thread(
        () -> {

            System.out.println("작업");
        }
    );
 

32. Thread 생성 비용

매우 중요.


Thread 하나 생성 시

OS 레벨에서:

Stack 생성
TCB 생성
스케줄링 등록
 

발생.


33. 그래서 문제

 
for(int i=0;i<100000;i++)
 

 
new Thread(...)
 

절대 하면 안 됨.


34. 그래서 등장

나중에 배울

 
ExecutorService
 

35. Thread 상태

대표 상태:

NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
 

36. 생성 직후

 
Thread t =
    new Thread(...);
 

NEW
 

37. start()

 
t.start();
 

RUNNABLE
 

38. 종료

run() 끝

TERMINATED
 

39. Thread.currentThread()

매우 자주 사용.


예:

 
Thread.currentThread()
 

의미

현재 실행 중인 Thread
 

40. 예시

 
System.out.println(
    Thread.currentThread()
          .getName()
);
 

출력

main
Thread-0
pool-1-thread-1
 

등.


41. 실무에서 Runnable 쓰는 이유

대표 이유:

상속 제한 없음
 

재사용 가능
 

ThreadPool 연계
 

ExecutorService 사용 가능
 

42. Thread vs Runnable 비교

항목ThreadRunnable
형태 클래스 인터페이스
상속 필요 O X
다중 구현 가능 X O
실무 사용 적음 많음
ExecutorService 사용 간접 직접

43. 실무 관점

현재는 사실

 
new Thread(...)
 

보다

 
ExecutorService
 

사용이 압도적으로 많음.


Thread
↓
Runnable
↓
ExecutorService
 

순으로 발전.


44. 면접 단골 질문

Q. Thread와 Runnable 차이는?

Thread
=
실행 주체

Runnable
=
실행할 작업
 

Q. run()과 start() 차이는?

run()
=
일반 메서드 호출

start()
=
새 Thread 생성
 

Q. 실무에서는 어떤 걸 더 많이 쓰나요?

Runnable
+
ExecutorService
 

Q. Thread를 상속하는 방식이 잘 안 쓰이는 이유는?

단일 상속 제한
역할 분리 어려움
 

45. 핵심 흐름 요약

Runnable
 ↓
Thread 생성
 ↓
start()
 ↓
OS 스케줄러 등록
 ↓
run() 실행
 

46. 가장 중요한 핵심 한 줄

Thread는 실행 주체이고,
Runnable은 실행할 작업이며,
실무에서는 Runnable을 Thread 또는 ExecutorService에 전달하는 방식이 가장 많이 사용된다.
 

다음 글은

synchronized 원리

입니다.

여기서부터 진짜 멀티스레드 문제가 시작됩니다.

  • Race Condition
  • Critical Section
  • Monitor Lock
  • Object Header
  • Biased Lock
  • Lightweight Lock
  • Heavyweight Lock

까지 JVM 내부 구조와 함께 연결됩니다.

반응형

댓글