
이번 포스팅에서는 Java에서 스레드를 활용하는 방법을 배워보고
멀티스레드 프로그래밍을 이해하고, 실제 코드를 통해 실행 흐름과 성능 최적화 방법을 익혀보려 한다
1. 멀티스레드란?
✅ 싱글스레드 vs 멀티스레드
- 싱글스레드: 한 번에 하나의 작업만 실행 (ex. StringBuilder)
- 멀티스레드: 여러 작업을 동시에 실행 (ex. StringBuffer)
✅ 멀티스레드의 장점
- CPU의 여러 코어를 활용하여 성능 최적화 가능
- 입출력(IO) 작업을 비동기 처리하여 응답 속도 개선
✅ 멀티스레드의 단점
- 동기화 문제 발생 가능 (synchronized 필요)
- 자원 관리가 어려워질 수 있음 (ExecutorService 활용)
2. 예제 코드 분석
🏆 기본적인 멀티스레드 실행
public class ThreadExample {
public static void main(String[] args) {
/***********************************************************************/
/***************************** 스레드 연습 ********************************/
/***********************************************************************/
System.out.println("작업 1 시작");
Thread thread1 = new Thread(new Task());
thread1.start(); // 새로운 스레드 실행
System.out.println("작업 2 시작");
Thread thread2 = new Thread(new Task());
thread2.start(); // 또 다른 스레드 실행
// 멀티스레드 최적화 코어 개수 설정
int threadsForCPU = Runtime.getRuntime().availableProcessors() + 1; // CPU 연산이 많은 경우
int threadsForIO = (Runtime.getRuntime().availableProcessors() * 2) + 1; // I/O 작업이 많은 경우
System.out.println("CPU 작업용 스레드 수: " + threadsForCPU);
System.out.println("I/O 작업용 스레드 수: " + threadsForIO);
// ExecutorService를 사용한 멀티스레드 처리 (스레드 풀 3개)
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 작업 수행 중...");
});
}
executor.shutdown(); // 모든 작업 요청 후 종료
System.out.println("모든 작업 요청 완료");
}
// Runnable 인터페이스를 활용한 스레드 작업 정의
static class Task implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 작업 중... " + i);
try {
Thread.sleep(1000); // 1초 대기(작업 하나 하는데 걸리는 시간)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
3. 실행 결과 예상
작업 1 시작
작업 2 시작
CPU 작업용 스레드 수: 9
I/O 작업용 스레드 수: 17
모든 작업 요청 완료
Thread-0 작업 중... 0
Thread-1 작업 중... 0
Thread-0 작업 중... 1
Thread-1 작업 중... 1
...
pool-1-thread-1 작업 수행 중...
pool-1-thread-2 작업 수행 중...
🔹 Thread-0, Thread-1이 동시에 실행
🔹 ExecutorService를 활용한 스레드 풀에서 작업 수행
4. Thread와 ExecutorService 차이점
방식
|
특징
|
사용 예
|
Thread
|
직접 생성 및 관리
|
간단한 스레드 실행
|
Runnable
|
Thread보다 가벼움, run() 메서드만 구현
|
멀티스레드 기본 작업
|
ExecutorService
|
스레드 풀을 사용하여 관리 효율적
|
대규모 병렬 처리, 안정적 관리
|
💡 멀티스레드 환경에서 직접 Thread를 생성하는 것보다 ExecutorService를 사용하는 것이 권장됨!
(스레드 개수를 제한하여 성능을 관리할 수 있기 때문)
5. ExecutorService 활용법
✅ 1) 고정된 개수의 스레드 풀
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new Task());
executor.shutdown();
✅ 2) 캐시된 스레드 풀 (필요할 때 생성)
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Task());
executor.shutdown();
✅ 3) 단일 스레드 실행 (순차 처리)
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(new Task());
executor.shutdown();
6. 멀티스레드 꿀팁
✔ 1) 스레드 동기화 (synchronized)
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
💡 여러 스레드가 동시에 접근할 때 데이터 충돌을 방지
✔ 2) Future를 활용한 비동기 작업 처리
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> future = executor.submit(() -> {
Thread.sleep(1000);
return 42;
});
System.out.println(future.get()); // 1초 후 결과 출력
executor.shutdown();
💡 비동기 작업을 실행하고 결과를 나중에 가져올 수 있음!
✔ 3) CountDownLatch를 활용한 스레드 동기화
CountDownLatch latch = new CountDownLatch(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 작업 완료");
latch.countDown(); // 하나의 작업 완료
});
}
latch.await(); // 모든 작업이 끝날 때까지 대기
System.out.println("모든 작업 완료!");
executor.shutdown();
💡 여러 개의 스레드가 작업을 마칠 때까지 대기할 수 있음
7. 마무리
📌 정리
✅ Thread, Runnable, ExecutorService를 활용하여 멀티스레드 프로그래밍 가능
✅ ExecutorService를 활용하면 스레드 관리를 더 효율적으로 할 수 있음
✅ synchronized, Future, CountDownLatch 등을 활용하여 동기화 문제 해결 가능
스레드 하나 잘쓰면 비용과 시간을 줄일 수 있기에 실무에서 아주 유용하고 자주 쓰이게 된다
고로 이후 포스팅에도 스레드에 관한 내용을 자주 다뤄보려고 한다!
학스의 개발일지
일상과 코딩 그 사이 어딘가에있는 블로그.. 블로거이자 빅데이터개발자 학스 입니다 JAVA, jQuery, PostgreSQL, MySQL, HIVE, Hadoop 더 많은 정보는 깃허브 주소 https://github.com/hacs2772 를 방문해주세요
hacs2772.tistory.com
오류나 궁금하신점은
아래 댓글로 알려주시면 감사하겠습니다.
'TIPS' 카테고리의 다른 글
멀티스레드 환경에서 발생할 수 있는 충돌 사례 및 해결 방법 (1) | 2025.05.06 |
---|---|
Java 멀티스레드에서 충돌 방지하기 (0) | 2025.04.28 |
문자열(String) 기본 개념 (0) | 2025.04.14 |
Java 정렬(sort) 기초 가이드 (0) | 2025.04.07 |
Java 예외 처리 (try-catch) 기초 가이드 (0) | 2025.04.01 |