Java 초보 개발자를 위한 멀티스레딩과 동시성

KUKJIN LEE's profile picture

KUKJIN LEE2개월 전 작성

Java에서 멀티스레딩과 동시성은 Spring Boot와 같은 프레임워크를 사용할 때 중요한 역할을 합니다. 초보 개발자가 멀티스레딩을 이해하고 Spring Boot 개발에 적용하기 위해 반드시 알아야 할 필수 개념입니다.

 

1. 스레드(Thread)란?

  • 정의: 스레드는 프로그램 내에서 독립적으로 실행될 수 있는 단위입니다. 기본적으로 모든 Java 프로그램은 메인 스레드를 포함하고 있으며, 개발자는 추가적인 스레드를 생성하여 병렬 처리를 할 수 있습니다.

 

2. 스레드 생성 방법

Java에서 스레드를 생성하는 기본적인 두 가지 방법은 다음과 같습니다.

  • 클래스 상속 (extends)

class MyThread extends Thread {
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();  // 스레드 시작
    }
}

Thread 클래스를 상속받는 방식은 클래스가 이미 Thread를 상속받고 있기 때문에 다른 클래스를 상속할 수 없습니다. 이는 상속에 제한이 있습니다.

 

인터페이스 구현 (implements)

interface Task1 {
    void task1();
}

interface Task2 {
    void task2();
}
class MyRunnable implements Runnable, Task1, Task2 {
    public void run() {
        System.out.println("Runnable is running");
    }

    public void task1() {
        System.out.println("Task 1 is executed");
    }

    public void task2() {
        System.out.println("Task 2 is executed");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable);
        t1.start();  // 스레드 시작

        // Task1과 Task2의 메서드도 호출 가능
        myRunnable.task1();
        myRunnable.task2();
    }
}

인터페이스를 구현하는 방식은 클래스가 다른 클래스를 상속받을 수 있으므로 더 큰 확장성을 가집니다. 인터페이스는 다중 구현이 가능하기 때문에 여러 기능을 동시에 구현할 수 있는 장점이 있습니다.

 

비교 요약:

  • extends: Thread 클래스를 상속받아 사용, 다른 클래스를 상속할 수 없음.

  • implements: Runnable 인터페이스를 구현하여 사용, 다른 클래스를 상속할 수 있으며 다중 인터페이스도 구현 가능.

 

3. 동기화(Synchronization)

  • 정의: 여러 스레드가 동시에 공유 자원에 접근할 때, 데이터의 일관성을 유지하기 위해 동기화가 필요합니다.

  • synchronized 키워드: 특정 메서드나 블록을 동기화하여 한 번에 하나의 스레드만 접근할 수 있게 만듭니다.

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

사용 이유: 동기화를 통해 여러 스레드가 동시에 한 객체에 접근하여 발생할 수 있는 데이터 불일치 문제를 해결할 수 있습니다.

 

4. 스레드 상태(Thread States)

Java 스레드는 실행 중 다양한 상태를 가질 수 있습니다. 이를 이해하면 스레드의 실행 흐름을 관리하는 데 도움이 됩니다.

  • NEW: 스레드가 생성되었지만 아직 시작되지 않은 상태.

  • RUNNABLE: 스레드가 실행 중이거나 실행 준비 상태.

  • BLOCKED: 스레드가 락을 기다리며 일시 중단된 상태.

  • WAITING: 다른 스레드가 특정 작업을 완료하기를 기다리는 상태.

  • TERMINATED: 스레드 실행이 완료된 상태.

이러한 상태는 스레드 실행 중 발생할 수 있는 문제를 디버깅할 때 유용합니다.

 

class MyThread extends Thread {
    public void run() {
        try {
            // 스레드 상태를 RUNNABLE 상태로 만든 후 일시 중지
            Thread.sleep(100); // TIMED_WAITING 상태
            synchronized (this) {
                wait(); // WAITING 상태
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();

        // NEW 상태: 스레드를 생성했지만 시작하지 않은 상태
        System.out.println("Thread state after creation: " + t1.getState());

        t1.start();

        // RUNNABLE 상태: 스레드가 실행 중이거나 실행 준비 상태
        System.out.println("Thread state after start: " + t1.getState());

        // 잠시 대기하여 스레드가 sleep에 진입할 시간을 줌
        Thread.sleep(50);
        System.out.println("Thread state during sleep (TIMED_WAITING): " + t1.getState());

        // 스레드가 wait에 진입할 시간을 줌
        Thread.sleep(150);
        System.out.println("Thread state during wait (WAITING): " + t1.getState());

        // 스레드가 WAITING 상태일 때 notify 호출
        synchronized (t1) {
            t1.notify(); // WAITING 상태에서 깨워줌
        }

        // 스레드가 종료될 때까지 기다림
        t1.join();
        // TERMINATED 상태: 스레드 실행이 완료된 상태
        System.out.println("Thread state after termination: " + t1.getState());
    }
}

 

5. extendsimplements의 의미

  • extends (확장하다): 클래스가 다른 클래스를 확장하여 그 기능을 물려받습니다. 상속 구조에서 부모 클래스의 기능을 자식 클래스에서 사용할 수 있게 됩니다.

  • implements (구현하다): 클래스가 인터페이스를 구현하여 인터페이스에 정의된 메서드들을 실제로 구현합니다. 여러 인터페이스를 동시에 구현할 수 있어 다중 기능을 제공할 수 있습니다.

 

  • 예시:

    • extends: 기존 클래스를 확장하여 상속받는 경우.

    • implements: 인터페이스를 구현하여 새로운 기능을 클래스에 추가하는 경우.

New Tech Posts