멀티스레딩 (Multithreading)
멀티스레딩은 하나의 프로세스에서 여러 개의 스레드가 동시에 실행될 수 있도록 하는 프로그래밍 기법입니다. Java에서는 Thread 클래스를 이용하여 스레드를 생성하고 관리할 수 있습니다.
스레드 생성 (Creating Threads)
스레드를 생성하는 방법에는 Thread 클래스를 상속받거나 Runnable 인터페이스를 구현하는 방법이 있습니다.
Thread 클래스를 상속받는 방법:
class MyThread extends Thread {
public void run() {
System.out.println("Thread 실행 중...");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 스레드 실행
}
}
Runnable 인터페이스를 구현하는 방법:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable 실행 중...");
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start(); // 스레드 실행
}
}
동기화 (Synchronization)
여러 스레드가 공유 자원에 접근할 때 데이터 불일치 문제를 해결하기 위해 동기화가 필요합니다. Java에서는 synchronized 키워드나 Lock 인터페이스를 사용하여 동기화를 구현할 수 있습니다.
synchronized 메서드를 사용한 동기화:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Counter 값: " + counter.getCount()); // 예상 결과: 2000
}
}
위의 예제에서 Counter 클래스의 increment()와 getCount() 메서드는 synchronized 키워드를 사용하여 동기화되었습니다. 따라서 여러 스레드가 동시에 increment() 메서드를 호출해도 count 변수의 일관된 증가가 보장됩니다.
스레드 상태 (Thread States)
Java에서 스레드는 여러 상태를 가질 수 있습니다. 주요 스레드 상태는 다음과 같습니다:
- NEW: 스레드 객체가 생성된 상태이지만
start()메서드가 호출되지 않은 상태입니다. - RUNNABLE: 스레드가 실행 중인 상태입니다.
- BLOCKED: 다른 스레드가 임계 영역을 점유하고 있어서 기다리고 있는 상태입니다.
- WAITING: 다른 스레드가
notify()또는notifyAll()메서드를 호출할 때까지 기다리는 상태입니다. - TIMED_WAITING: 주어진 시간 동안 기다리는 상태입니다.
- TERMINATED: 스레드의 실행이 종료된 상태입니다.
public class ThreadStateExample {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("스레드 상태: " + thread.getState()); // NEW
thread.start();
Thread.sleep(500);
System.out.println("스레드 상태: " + thread.getState()); // RUNNABLE
Thread.sleep(1500);
System.out.println("스레드 상태: " + thread.getState()); // TERMINATED
}
}
위의 예제에서는 Thread 객체를 생성하고 상태를 출력하여 스레드의 생명 주기를 관찰할 수 있습니다.
