학습
Java 다중 스레드 프로그래밍
Java 다중 스레드 프로그래밍 — 중급
다중 스레드 프로그래밍
1. 도입 (왜 배워야 하는가)
다중 스레드 프로그래밍은 현대 소프트웨어 개발에서 필수적인 기술입니다. 특히 멀티코어 프로세서가 일반화된 오늘날, 다중 스레드를 활용하면 여러 작업을 동시에 수행할 수 있어 시스템의 효율성을 극대화할 수 있습니다.
예를 들어, 웹 서버는 동시에 여러 사용자의 요청을 처리해야 하며, 이는 다중 스레드를 통해 이루어집니다. 만약 다중 스레드를 활용하지 않는다면, 사용자의 요청이 순차적으로 처리되어 서버의 응답 속도가 느려지고 사용자 경험이 저하됩니다. 따라서 다중 스레드 프로그래밍을 이해하고 활용하는 것은 실무에서 매우 중요한 역량입니다.
2. 핵심 개념 설명
스레드(Thread)
스레드는 프로세스 내에서 실행되는 가장 작은 실행 단위입니다. 여러 스레드를 통해 하나의 프로세스가 동시에 여러 작업을 수행할 수 있습니다. 스레드는 서로 독립적으로 실행되므로 작업의 효율성을 높일 수 있습니다.
멀티스레딩(Multithreading)
멀티스레딩은 하나의 프로세스 내에서 여러 스레드가 동시에 실행되는 상태를 의미합니다. 이는 일종의 파티에서 여러 사람들이 동시에 이야기하는 것과 비슷합니다. 각 사람(스레드)은 독립적으로 대화하지만, 같은 공간(프로세스) 안에서 이루어집니다.
관련 용어 정리
| 용어 | 설명 |
|---|---|
| 동기화(Synchronization) | 여러 스레드가 공유 자원에 접근할 때 발생할 수 있는 문제를 해결하는 기법. |
| 경쟁 상태(Race Condition) | 두 개 이상의 스레드가 동시에 공유 자원에 접근할 때 발생하는 불일치 상태. |
| 데드락(Deadlock) | 두 개 이상의 스레드가 서로의 자원을 기다리며 무한 대기 상태에 빠지는 현상. |
3. 기본 코드 예제
다중 스레드를 사용하여 간단한 카운터를 구현해보겠습니다.
class Counter extends Thread {
private int count = 0;
public void run() {
for (int i = 0; i < 5; i++) {
count++;
System.out.println("Current Count: " + count);
try {
Thread.sleep(500); // 0.5초 대기
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
counter1.start(); // 첫 번째 스레드 시작
counter2.start(); // 두 번째 스레드 시작
}
}
실행 결과
Current Count: 1
Current Count: 1
Current Count: 2
Current Count: 2
Current Count: 3
Current Count: 3
Current Count: 4
Current Count: 4
Current Count: 5
Current Count: 5
코드 한 줄씩 동작 설명
Counter클래스는Thread클래스를 상속받아 스레드를 생성합니다.run()메소드에서 카운트를 5까지 증가시키며, 각각의 증가 후 0.5초 동안 대기합니다.main()메소드에서 두 개의Counter객체를 생성하고 각각의 스레드를 시작합니다.start()메소드는 스레드를 실행시키고, 각 스레드는run()메소드를 호출하여 동작합니다.- 잘못된 코드:
- 올바른 코드:
- 잘못된 코드:
- 올바른 코드:
- 다중 스레드 프로그래밍은 멀티코어 CPU를 활용하여 효율성을 높이는 기술입니다.
- 스레드, 멀티스레딩, 동기화 등 기본 개념을 이해해야 합니다.
- 실전 예제로는 장바구니 업데이트 및 파일 다운로드를 활용할 수 있습니다.
- 다음에 학습하면 좋은 주제로는 스레드 풀(Thread Pool)과 비동기 프로그래밍이 있습니다.
4. 실전 활용 예제
예제 1: 쇼핑몰 장바구니 업데이트
쇼핑몰에서 여러 사용자가 동시에 장바구니에 상품을 추가할 때, 각 스레드는 독립적으로 장바구니를 업데이트 할 수 있습니다. 이때 동기화가 필요하여 경쟁 상태를 방지해야 합니다.
class ShoppingCart {
private int itemCount = 0;
public synchronized void addItem() {
itemCount++;
System.out.println("Item added. Current count: " + itemCount);
}
}
class User extends Thread {
ShoppingCart cart;
User(ShoppingCart cart) {
this.cart = cart;
}
public void run() {
for (int i = 0; i < 3; i++) {
cart.addItem();
try {
Thread.sleep(300); // 0.3초 대기
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 메인 메소드에서 여러 User 객체를 생성하여 장바구니에 상품을 추가합니다.
예제 2: 파일 다운로드
파일을 여러 스레드를 통해 동시에 다운로드하는 경우, 각 스레드는 별도의 파일 조각을 다운로드하여 전체 다운로드 시간을 줄일 수 있습니다.
5. 흔한 실수와 주의사항
실수 1: 스레드 안전성 미확인
Counter counter = new Counter(); // 여러 스레드에서 공유
counter.start();
counter.start(); // 두 번 시작 시 예외 발생
Counter counter1 = new Counter();
Counter counter2 = new Counter();
counter1.start();
counter2.start(); // 독립된 스레드로 실행
실수 2: 동기화 부족
public void addItem() {
itemCount++; // 경쟁 상태 발생 가능
}
public synchronized void addItem() {
itemCount++;
}