JAVA chapter12. 멀티 스레드. 12.9 스레드풀 // 추가하기
JAVA/CONCEPT 2017. 11. 30. 17:57 |chapter12. 멀티 스레드. 12.9 스레드풀
* 스레드 폭증
- 병렬 작업 처리가 많아지면 스레드의 개수가 증가
- 스레드 생성과 스케쥴링으로 인해 CPU가 바빠지고, 메모리 사용량이 늘어난다
- 따라서 애플리케이션의 성능이 급격히 저하된다.
* 스레드풀(Thread Pool)
- 작업 처리에 사용되는 스레드를 제한된 개수만큼 미리 생성
- 작업 큐(Queue)에 들어오는 작업들을 하나씩 스레드가 맡아 처리
- 작업 처리가 끝난 스레드는 작업 결과를 애플리케이션으로 전달
- 스레드는 다시 작업큐에서 새로운 작업을 가져와 처리
* ExecutorService 인터페이스와 Executors 클래스
- 스레드풀을 생성하고 사용할 수 있도록 java.util.concurrent 패키지에서 제공
- Executors의 정적 메소드를 이용해서 ExecutorService 구현 객체 생성
- 스레드풀 = ExecutorService 객체
* ExecutorService 동작 원리
12.9.1 스레드풀 생성 및 종료
* 스레드풀 생성
- 다음 두가지 메소드 중 하나로 간편 생성
- newCachedThreadPool()
// int값이 가질 수 있는 최대 값만큼 스레드가 추가되나, 운영체제의 상황에 따라 달라진다.
// 1개 이상의 스레드가 추가되었을 경우
// 60초 동안 추가된 스레드가 아무 작업을 하지 않으면
// 추가된 스레드를 종료하고 풀에서 제거한다
- newFixedThreadPool(int n Threads)
// 코어 스레드 개수와 최대 스레드 개수가 매개값으로 준 nThread이다.
// 스레드가 작업을 처리하지 않고 놀고 있더라도 스레드 개수가 줄지 않는다
- ThreadPoolExecutor을 이용한 직접 생성
// newCachedThreadPool()과 newFixedThreadPool(int n Threads)가 내부적으로 생성
// 스레드의 수를 자동을 관리하고 싶을 경우 직접 생성해서 사용
ex)
// 코어 스레드 개수가 3, 최대 스레드 개수가 100인 스레드풀을 생성
// 3개를 제외한 나머지 추가된 스레드가 120초 동안 놀고 있을 경우
// 해당 스레드를 제거해서 스레드 수를 관리
* 스레드풀 종료
- 스레드풀의 스레드는 기본적으로 데몬 스레드가 아니다.
// main 스레드가 종료되더라도 스레드풀의 스레드는 작업을 처리하기 위해 계속 실행되므로
// 애플리케이션은 종료되지 않는다
// 따라서 스레드풀을 종료해서 모든 스레드를 종료시켜야 한다.
12.9.2 작업 생성과 처리 요청
* 작업 생성
- 하나의 작업은 Runnable 또는 Callable 객체로 표현한다
- Runnable과 Callable의 차이점
// 작업 처리 완료 후 리턴값이 있느냐 없느냐
- 스레드풀에서 작업 처리
// 작업 큐에서 Runnable 또는 Callable 객체를 가져와
// 스레드로 하여금 run()과 call() 메소드를 실행토록 하는 것이다.
* 작업 처리 요청
- ExecutorService의 작업 큐에 Runnable 또는 Callable 객체를 넣는 행위를 말한다.
- 작업 처리 요청을 위해 ExecutorService는 다음 두 가지 종류의 메소드를 제공한다
- 작업 처리 도중 예외가 발생할 경우
// execute()
: 스레드가 종료되고 해당 스레드는 제거된다
: 따라서 스레드풀은 다른 작업 처리를 위해 새로운 스레드를 생성한다.
// submit()
: 스레드가 종료되지 않고 다음 작업을 위해 재사용된다.
execute() 메소드로 작업 처리 요청한 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package sec09.exam01_execute_submit; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; public class ExecuteVsSubmitExample { public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(2); // 쵀대 스레드 개수가 2인 스레드풀 생성 ////////////////////////// for(int i=0; i<10; i++) { // 작업 정의 Runnable runnable = new Runnable() { @Override public void run() { //스레드 총 개수 및 작업 스레드 이름 출력 ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService; int poolSize = threadPoolExecutor.getPoolSize(); String threadName = Thread.currentThread().getName(); System.out.println("[총 스레드 개수: " + poolSize + "] 작업 스레드 이름: " + threadName); //예외 발생 시킴 int value = Integer.parseInt("삼"); } }; executorService.execute(runnable); // 작업 처리 요청 //executorService.submit(runnable); //////////////////////// Thread.sleep(10); } executorService.shutdown(); // 스레드풀 종료 } } |
12.9.3 블로킹 방식의 작업 완료 통보
- Future
// 작업 결과가 아니라 지연 완료(pending completion) 객체
// 작업이 완료될때까지 기다렸다가 최종 결과를 얻기위해서 get() 메소드를 사용
'JAVA > CONCEPT' 카테고리의 다른 글
JAVA chapter13. 제네릭. 13.3 멀티 타입 파라미터(class<K,V,...>, interface<K,V,...>) (0) | 2017.11.30 |
---|---|
JAVA chapter13. 제네릭. 13.1 왜 제네릭을 사용해야 되는가? 13.2 제네릭 타입(class<T>, interface<T>) (0) | 2017.11.30 |
JAVA chapter12. 멀티 스레드. 12.8 스레드 그룹 (0) | 2017.11.29 |
JAVA chapter12. 멀티 스레드. 12.7 데몬 스레드 (0) | 2017.11.29 |
JAVA chapter12. 멀티 스레드. 12.6 스레드 상태 제어 (0) | 2017.11.29 |