스레드 풀(Thread Pool)
스레드 풀은 일정 수의 스레드를 미리 생성하여 관리하는 기법입니다.
작업 큐에 새로운 작업이 들어오면, 스레드 풀에서 사용 가능한 스레드가 해당 작업을 처리하고
작업이 완료되면, 해당 스레드는 다음 작업을 위해 다시 풀에 반환됩니다.
사용 이유
- 자원 관리: 스레드 생성과 소멸의 오버헤드를 줄이고, 자원을 효율적으로 관리할 수 있습니다.
- 제한된 스레드 수: 시스템에서 생성할 수 있는 스레드 수를 제한함으로써 자원 고갈 및 성능 저하를 방지할 수 있습니다.
- 응답성 및 처리량 향상: 미리 생성된 스레드를 재사용(작업을 대기상태로 유지)함으로써 성능을 향상시킬 수 있고, 작업이 발생하면 대기 중인 쓰레드 중 하나를 선택하여 작업을 할당하므로, 작업 처리를 병렬로 진행할 수 있습니다.
Executor
Executor는 Java에서 스레드를 실행하는 방법을 추상화한 인터페이스입니다. Executor를 사용하면 스레드를 직접 생성하고 관리하는 대신, 작업을 Executor에 제출하면 됩니다. ExecutorService는 Executor의 하위 인터페이스로, 스레드 풀을 관리하고 제어할 수 있는 기능을 제공합니다.
주요 메서드
- execute(Runnable command): 주어진 Runnable 작업을 실행합니다.
- submit(Callable<T> task) / submit(Runnable task) : 주어진 Callable / Runnable 작업을 실행하고, Future 객체를 반환합니다.
- shutdown(): 더 이상 새로운 작업을 받지 않고, 현재 실행 중인 작업들을 완료한 후 종료합니다.
- shutdownNow(): 현재 실행 중인 작업들을 중지하고, 스레드 풀을 즉시 종료합니다.
스레드 풀의 유형
Java에서 제공하는 다양한 유형의 스레드 풀이 있습니다:
- FixedThreadPool
- 고정된 수의 스레드를 유지하는 스레드 풀입니다. 초과된 작업은 내부 큐에서 대기합니다.
- 예시: Executors.newFixedThreadPool(3);
- CachedThreadPool
- 필요할 때 스레드를 생성하고, 일정 시간 동안 사용되지 않은 스레드를 제거합니다.
- 예시: Executors.newCachedThreadPool();
- SingleThreadExecutor
- 단일 스레드로 작업을 처리합니다. 순차적으로 작업을 처리하고, 스레드가 종료되지 않도록 유지합니다.
- 예시: Executors.newSingleThreadExecutor();
- ScheduledThreadPool
- 일정 시간 후 또는 주기적으로 작업을 실행합니다.
- 예시: Executors.newScheduledThreadPool(3);
*참고: 스레드가 수행할 작업을 정의 (Callable, Runnable)
예제 1: 기본적인 스레드 풀 생성 및 사용
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 고정된 크기의 스레드 풀 생성
ExecutorService executorService = Executors.newFixedThreadPool(3);
// Runnable 작업 정의
Runnable task = () -> {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " is executing task.");
};
// 작업을 스레드 풀에 제출
for (int i = 0; i < 10; i++) {
executorService.execute(task);
}
// 스레드 풀 종료
executorService.shutdown();
}
}
위 예제는 3개의 스레드를 가진 스레드 풀을 생성하고, 10개의 Runnable 작업을 제출하여 실행하는 간단한 예제입니다. executorService.shutdown()을 호출하여 더 이상 새로운 작업을 받지 않도록 하고, 현재 실행 중인 작업들을 완료한 후 종료합니다.
예제 2: Callable과 Future를 사용한 예제
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableExample {
public static void main(String[] args) {
// 고정된 크기의 스레드 풀 생성
ExecutorService executorService = Executors.newFixedThreadPool(3);
// Callable 작업 정의
Callable<String> task = () -> {
String threadName = Thread.currentThread().getName();
return threadName + " is executing task.";
};
// 작업을 스레드 풀에 제출하고 Future 객체 반환받기
Future<String> future = executorService.submit(task);
try {
// Future 객체로부터 결과 가져오기
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 스레드 풀 종료
executorService.shutdown();
}
}
위 예제는 Callable 인터페이스를 사용하여 작업을 정의하고, 해당 작업을 스레드 풀에 제출하여 Future 객체를 반환받습니다. future.get()을 호출하여 작업의 결과를 가져옵니다.
'Backend > JAVA' 카테고리의 다른 글
블록킹큐(Blocking Queue) (0) | 2024.06.05 |
---|---|
Callable, Runnable, Future (0) | 2024.06.05 |
[Java] java.lang 패키지의 System (0) | 2023.10.12 |
JAVA에서 html 다루기 (Jsoup) (0) | 2023.08.16 |
[JAVA] 패키지와 클래스 (같은 이름의 클래스 import) (0) | 2023.07.25 |