본문 바로가기
자바 (JAVA)

📚 JAVA 11강: 스레드(Thread)

by demianpark127 2025. 1. 3.
SMALL

📚 11강: 스레드(Thread)


🚀 1. 스레드(Thread)란?

  • **스레드(Thread)**는 프로그램 내에서 실행되는 가장 작은 작업 단위입니다.
  • 하나의 프로그램(프로세스) 내에서 여러 스레드가 동시에 작업을 수행할 수 있습니다.
  • Java에서는 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하여 스레드를 생성합니다.

🚀 2. 자바에서 스레드 생성 방법

📌 2.1 Thread 클래스를 상속받는 방법

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " 실행 중: " + i);
        }
    }
}

public class ThreadExample1 {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        thread1.start(); // 스레드 실행
        thread2.start(); // 스레드 실행
    }
}
Thread-0 실행 중: 0
Thread-1 실행 중: 0
Thread-0 실행 중: 1
Thread-1 실행 중: 1

📝 설명:

  • MyThread 클래스가 Thread 클래스를 상속받아 run() 메서드를 오버라이딩합니다.
  • start() 메서드를 호출하면 run() 메서드가 실행됩니다.

📌 2.2 Runnable 인터페이스를 구현하는 방법

 

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " 실행 중: " + i);
        }
    }
}

public class ThreadExample2 {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);

        thread1.start();
        thread2.start();
    }
}
Thread-0 실행 중: 0
Thread-1 실행 중: 0
Thread-0 실행 중: 1
Thread-1 실행 중: 1

📝 설명:

  • MyRunnable 클래스가 Runnable 인터페이스를 구현합니다.
  • Thread 객체에 Runnable 객체를 전달하여 스레드를 실행합니다.

🚀 3. 스레드의 상태(Thread State)

 

상태 설명
NEW 스레드 객체가 생성되었지만 아직 실행되지 않음.
RUNNABLE 스레드가 실행 중이거나 실행 가능한 상태.
BLOCKED 스레드가 다른 스레드에 의해 잠겨있는 상태.
WAITING 다른 스레드의 작업이 끝날 때까지 기다리는 상태.
TIMED_WAITING 지정된 시간 동안 기다리는 상태.
TERMINATED 스레드가 종료된 상태.

🚀 4. 스레드 우선순위(Thread Priority)

  • 스레드 우선순위는 1 (낮음) ~ 10 (높음) 범위에서 설정됩니다.
  • 기본값은 5입니다.
  • setPriority(int priority)로 설정 가능.
class PriorityThread extends Thread {
    @Override
    public void run() {
        System.out.println(getName() + "의 우선순위: " + getPriority());
    }
}

public class ThreadPriorityExample {
    public static void main(String[] args) {
        PriorityThread thread1 = new PriorityThread();
        PriorityThread thread2 = new PriorityThread();

        thread1.setPriority(Thread.MIN_PRIORITY); // 1
        thread2.setPriority(Thread.MAX_PRIORITY); // 10

        thread1.start();
        thread2.start();
    }
}

📌 출력 예시:


Thread-0의 우선순위: 1
Thread-1의 우선순위: 10

🚀 5. 동기화(Synchronization)

  • 여러 스레드가 하나의 공유 자원에 접근할 때 발생할 수 있는 문제를 해결하기 위해 사용됩니다.
  • synchronized 키워드를 사용하여 동기화합니다.
class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
        System.out.println(Thread.currentThread().getName() + ": " + count);
    }
}

public class SynchronizationExample {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Runnable task = () -> {
            for (int i = 0; i < 5; i++) {
                counter.increment();
            }
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();
    }
}

📌 출력 예시:

Thread-0: 1
Thread-1: 2
Thread-0: 3
Thread-1: 4

📝 설명:

  • synchronized를 사용해 increment() 메서드를 보호합니다.
  • 하나의 스레드만 메서드에 접근할 수 있습니다.

🚀 6. 실습 과제

1. 스레드 생성 및 실행

  • Thread 클래스를 상속받아 두 개의 스레드를 생성하고 실행하세요.
class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " 실행 중: " + i);
            try {
                Thread.sleep(500); // 0.5초 대기
            } catch (InterruptedException e) {
                System.out.println("스레드가 중단되었습니다.");
            }
        }
    }
}

public class ThreadExample1 {
    public static void main(String[] args) {
        MyThread threa

✅ 출력 예시

Thread-0 실행 중: 1
Thread-1 실행 중: 1
Thread-0 실행 중: 2
Thread-1 실행 중: 2

📌 설명:

  • MyThread 클래스가 Thread를 상속받고 run() 메서드를 오버라이딩합니다.
  • start() 메서드로 두 스레드를 실행합니다.
  • sleep() 메서드로 각 단계마다 잠시 대기합니다.

 

2. Runnable 사용

  • Runnable 인터페이스를 구현해 두 개의 스레드를 실행하세요.
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " 실행 중: " + i);
            try {
                Thread.sleep(500); // 0.5초 대기
            } catch (InterruptedException e) {
                System.out.println("스레드가 중단되었습니다.");
            }
        }
    }
}

public class ThreadExample2 {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);

        thread1.start(); // 스레드 실행
        thread2.start(); // 스레드 실행
    }
}

✅ 출력 예시

Thread-0 실행 중: 1
Thread-1 실행 중: 1
Thread-0 실행 중: 2
Thread-1 실행 중: 2
...

📌 설명:

MyRunnable이 Runnable 인터페이스를 구현합니다.
Thread 객체를 생성할 때 MyRunnable 객체를 전달합니다.
start()로 두 스레드를 실행합니다.

3. 동기화 연습

  • 공유 자원을 두 스레드가 동시에 접근하도록 하고, synchronized 키워드를 사용해 데이터 무결성을 보장하세요.
// 공유 자원 클래스
class Counter {
    private int count = 0;

    // 동기화된 메서드
    public synchronized void increment() {
        count++;
        System.out.println(Thread.currentThread().getName() + " - Count: " + count);
    }
}

// 스레드 클래스
class CounterThread extends Thread {
    private final Counter counter;

    public CounterThread(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            counter.increment();
            try {
                Thread.sleep(500); // 0.5초 대기
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "가 중단되었습니다.");
            }
        }
    }
}

public class SynchronizationExample {
    public static void main(String[] args) {
        Counter counter = new Counter();

        CounterThread thread1 = new CounterThread(counter);
        CounterThread thread2 = new CounterThread(counter);

        thread1.start();
        thread2.start();
    }
}

✅ 출력 예시

Thread-0 - Count: 1
Thread-1 - Count: 2
Thread-0 - Count: 3
Thread-1 - Count: 4
...

📌 설명:

synchronized 키워드를 사용하여 increment() 메서드를 보호합니다.
하나의 스레드만 동시에 increment()에 접근할 수 있습니다.

4. 우선순위 설정

  • 스레드의 우선순위를 각각 MAX_PRIORITY, MIN_PRIORITY로 설정하고 실행 결과를 확인하세요.
class PriorityThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " 우선순위: " + getPriority());
            try {
                Thread.sleep(500); // 0.5초 대기
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "가 중단되었습니다.");
            }
        }
    }
}

public class ThreadPriorityExample {
    public static void main(String[] args) {
        PriorityThread thread1 = new PriorityThread();
        PriorityThread thread2 = new PriorityThread();

        thread1.setPriority(Thread.MIN_PRIORITY); // 우선순위 1
        thread2.setPriority(Thread.MAX_PRIORITY); // 우선순위 10

        thread1.start();
        thread2.start();
    }
}

✅ 출력 예시

Thread-0 우선순위: 1
Thread-1 우선순위: 10
Thread-1 우선순위: 10
Thread-0 우선순위: 1
...

📌 설명:

setPriority()를 사용하여 스레드 우선순위를 설정합니다.
MIN_PRIORITY: 1 (낮음)
MAX_PRIORITY: 10 (높음)

🎯 7. 학습 목표

  1. Thread 클래스와 Runnable 인터페이스를 사용하여 스레드를 생성하고 실행할 수 있다.
  2. 스레드의 상태와 생명주기를 이해한다.
  3. 스레드의 우선순위를 설정할 수 있다.
  4. synchronized 키워드를 사용해 동기화 문제를 해결할 수 있다.
  5. 여러 스레드가 동시에 실행될 때 발생할 수 있는 문제를 예측하고 방지할 수 있다.

다음 강의 예고: 12강 - JDBC (Java Database Connectivity)

다음 강의에서는 **자바 데이터베이스 연결(JDBC)**을 학습합니다. 😊

LIST