Love Every Moment
〔Java〕쓰레드 풀(Thread Pool) 본문
1. 풀(Pool)
- 이미 사용할 준비가 된 자원을 메모리 위에 일정량 미리 생성해둔 자원의 집합
- 자원이 필요한 경우 새로 자원을 생성하는 대신 풀에서 꺼내어 사용
- 자원 사용을 완료한 경우 자원을 해제하는 대신 풀에 다시 반환
자원의 생성과 파괴에 드는 비용, 즉 오버헤드(Overhead)를 줄여준다는 장점이 있다
2. 쓰레드 풀(Thread Pool)
- 미리 쓰레드들을 생성해두었다가 작업 요청이 들어올 때마다 미리 생성된 쓰레드로 작업을 처리
- 작업이 끝난 쓰레드는 종료되지 않고 다음 작업 요청을 기다린다
- 쓰레드들을 풀에 생성 → 작업들을 태스크 큐(Task Queue)에 추가 → 쓰레드 별로 작업을 할당하여 처리
3. 쓰레드 풀의 생성
java.util.concurrent 패키지의 Executors 클래스의 메소드를 이용하여 ExecutorService 객체 생성
(1) newCachedThreadPool()
ExecutorService threadPool = Executors.newCachedThreadPool();
- 작업 요청이 들어올 때마다 쓰레드를 생성
- 생성된 쓰레드가 60초동안 유휴 상태이면 제거됨
- 초기 쓰레드 수: 0개
- 코어 쓰레드 수: 0개
- 최대 쓰레드 수: Integer.MAX_VALUE
(2) newFixedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(100);
- 현재 존재하는 쓰레드 수보다 작업량이 많으면 쓰레드를 생성
- 한 번 생성된 쓰레드는 유휴 상태가 오래 지나도 제거되지 않음
- 초기 쓰레드 수: 0개
- 코어 쓰레드 수: 쓰레드풀 생성시 지정
- 최대 쓰레드 수: 쓰레드풀 생성시 지정
(3) ThreadPoolExecutor()
ExecutorService threadPool = new ThreadPoolExecutor(
3, // 코어 쓰레드 수
100, // 최대 쓰레드 수
60, // 최대 유휴 시간
TimeUnit.SECONDS, // 최대 유휴 시간 단위
new LinkedBlockingQueue<Runnable>() // 작업 큐
);
- 초기, 코어, 최대 쓰레드 수를 모두 마음대로 지정해서 쓰레드 풀을 생성하는 방법
- 위의 newCachedThreadPool() 과 newFixedThreadPool() 도 내부적으로는 ThreadPoolExecutor()를 이용하여 구현되어 있음
4. 쓰레드 풀의 종료
(1) shutdown()
threadPool.shutdown();
- 현재 쓰레드들이 처리하고 있는 작업과 작업 큐에 대기하고 있는 작업을 모두 끝마친 뒤에 쓰레드 풀을 종료
(2) shutdownNow()
List<Runnable> unprocessedTasks = threadPool.shutdownNow();
- 현재 작업 중인 쓰레드를 강제 종료
- 작업 큐 대기열에 남아있는 작업들은 List<Runnable> 로 반환
(3) awaitTermination()
boolean complete = threadPool.awaitTermination(60, TimeUnit.SECONDS);
- shutdown() 을 먼저 호출
- 지정한 timeout 안에 모든 작업이 완료되면 true 를 반환
- 완료되지 못하면 작업을 처리 중이던 쓰레드를 강제 종료하고 false 를 반환
5. 쓰레드 풀에 작업 처리 요청
(1) execute()
- Runnable 만 처리 가능
- 작업의 처리 결과를 반환하지 않음
- 쓰레드가 작업 처리 중에 예외가 발생하면, 쓰레드 풀에서 해당 쓰레드를 제거하고 새로운 쓰레드 생성
(2) submit()
- Runnable 과 Callable 모두 처리 가능
- 작업의 처리 결과를 Future 라는 인터페이스로 반환(→자바스크립트의 Promise 와 유사)
- 작업 처리 중에 예외가 발생하더라도 쓰레드를 제거하지 않고 다음 작업에 재사용
- 일반적으로 submit() 이 execute() 보다 오버헤드가 적으므로 권장됨
public class myCallable implements Callable {
@Override
public Integer call() {
int count = 0;
for (int i = 0; i < 10; i++) {
try {
count += 1;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return count;
}
}
Future<?> future = executorService.submit(new myCallable());
try {
Object result = future.get(); // (1) 10초 동안 blocking 되었다가 반환
System.out.println("10s"); // (2) 10초 후에 출력
System.out.println("result = " + result); // (3) result = 10
} catch (Exception e) {
e.printStackTrace();
}
참고
자바에서 쓰레드 풀 다뤄보기
프로세스와 쓰레드 쓰레드는 프로세스 내의 작업 흐름이다. 프로세스는 최소 1개의 쓰레드를 가지고 있으며, N개의 쓰레드를 생성하여 동시에 작업이 처리 되도록 구성할 수 있다. 이렇게 프로
hudi.blog
🧶 Java 에서 스레드 풀(Thread Pool) 을 사용해 보자
프로세스 내에서 스레드의 생성 및 수거가 빈번하게 발생한다면 메모리 할당에 소모되는 비용이 많이 들지 않을까? 이에 대한 해답으로 스레드 풀에 대해 알아보고 Java 에서 어떻게 사용하면 되
tecoble.techcourse.co.kr
자바와 쓰레드풀, 쓰레드의 생성비용
멀티 쓰레드와 생성비용
velog.io
[자바 무료 강의] Thread Pool
이번 강의는 Thread를 담고 있는 Thread Pool에 대해서 배워봅시다. 현업에서는 Thread Pool을 이용하여 작업을 처리하는 경우가 많습니다.
www.codelatte.io
Introduction to Thread Pools in Java | Baeldung
[Java] 멀티스레드를 통한 성능개선
화스트 페이스 경보 발생... 문제상황 프로젝트 진행 중 이번달 말에 계산을 돌려야하는데 시간이 오래 걸린다고 성능을 개선해달라는 요청을 받았다. Slow Query가 있겠거니 하고 소스를 뜯어봤더
foot-develop.tistory.com
ThreadPoolExecutor에 대한 오해와 진실
ThreadPoolExecutor에 대한 오해와 진실
leeyh0216.github.io
'PROGRAMMING::LANGUAGE > Java' 카테고리의 다른 글
〔Java〕해시맵(HashMap)과 해시테이블(HashTable) (0) | 2023.07.31 |
---|