자바 Java Thread 개념 정리 (멀티태스킹의 시작)

scminy0527·2026년 3월 5일
post-thumbnail

자바에서 프로그램을 실행하면 기본적으로 하나의 작업 흐름이 실행됩니다.

하지만 현실의 프로그램을 보면 대부분 여러 작업을 동시에 수행합니다.

예를 들어 음악 플레이어를 생각해보면

  • 음악 재생
  • UI 표시
  • 다운로드
  • 사용자 입력 처리

이 모든 작업이 동시에 이루어집니다.

이때 이러한 동시에 실행되는 작업 흐름을 처리하기 위해 사용하는 것이 바로 Thread(스레드) 입니다.


Thread란 무엇인가?

Thread(스레드) 는 하나의 프로그램 안에서 실행되는 작업의 흐름입니다.

조금 더 쉽게 말하면

하나의 프로그램 안에서 동시에 여러 작업을 수행할 수 있도록 만들어주는 실행 단위

라고 볼 수 있습니다.

구조를 간단하게 보면 다음과 같습니다.

Program (Process)
 ├ Thread 1
 ├ Thread 2
 └ Thread 3

하나의 프로그램 안에 여러 개의 스레드가 존재할 수 있으며
이를 통해 멀티태스킹이 가능해집니다.


자바에서 스레드를 만드는 방법

자바에서는 스레드를 만드는 방법이 크게 두 가지 있습니다.

  1. Thread 클래스 상속
  2. Runnable 인터페이스 구현

1. Thread 클래스 상속

가장 기본적인 방법은 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()

start()

스레드를 실제로 실행시키는 메서드입니다.

주의할 점이 하나 있습니다.

run() 직접 호출 ❌
start() 호출 ⭕

왜냐하면

run() → 일반 메서드 호출
start() → 새로운 스레드 생성 후 run() 실행

이기 때문입니다.


2. Runnable 인터페이스 구현

자바에서는 사실 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() 메서드의 의미

스레드를 사용하다 보면 실행 순서를 제어해야 할 때가 있습니다.

이때 사용하는 메서드가 바로

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도 사실 하나의 스레드이다

자바 프로그램을 실행하면 사실 이미 하나의 스레드가 존재합니다.

바로

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 스케줄러

가 결정하기 때문입니다.

따라서 멀티스레드 환경에서는 실행 순서가 보장되지 않습니다.


정리

자바 스레드는

  • 하나의 프로그램에서 여러 작업을 동시에 수행하기 위한 실행 흐름이다
  • run() 메서드에 실행할 작업을 정의한다
  • start() 를 호출하면 새로운 스레드가 생성되어 실행된다
  • join() 은 해당 스레드가 끝날 때까지 기다리게 하는 기능이다

스레드를 이해하면

  • 멀티태스킹
  • 비동기 처리
  • 서버 프로그램
  • 네트워크 프로그램

같은 개념을 이해하는 데 큰 도움이 됩니다.

profile
비전공자에서 시작해 Flutter로 실서비스를 만들었고, 더 깊은 개발을 향해 계속 성장 중인 개발자

0개의 댓글