[Java] Thread#6, 스레드 풀 예제 및 개념(Future 객체, execute(), submit())
스레드풀
- 병렬작업 처리가 많아지면 스레드 개수 증가 -> 스레드 생성 및 스케쥴링을 CPU가 바빠져서 메모리 많이 사용
- 결국 성능저하.
- 갑작스런 병렬 작업처리가 많아질 때 스레드풀을 이용.
- 스레드를 제한된 개수만큼 정해놓고 작업큐(Queue)에 들어오는 작업들을 하나씩 스레드가 맡아서 처리.
- 스레드풀 생성/사용을 위해 Executors 클래스와 ExecutorService 인터페이스를 제공.
- Executors의 다양한 정적메소드로 ExecutorService의 구현객체를 만들 수 있는데 이것이 바로 스레드풀.
스레드풀 생성
Executors 클래스
- newCachedThreadPool()
- newFixedThreadPool()
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService2 = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors();
); //cpu의 코어수만큼 최대스레드풀 생성
스레드풀 종료
executorService.shutdown() - 남아있는 작업을 마무리하고 스레드풀 종료!
executorService.shutdownNow() - 남아있는 작업과는 상관없이 강제로 종료!
작업생성과 처리요청
작업생성
- 하나의 작업은 Runnable or Callable 구현 클래스로 표현한다.
- Runnable(무)과 Callable(유)의 차이는 리턴값의 유무이다.
Runnable task = new Runnable(){
@Override
public void run(){ /*스레드가 처리할 작업 내용*/ }
}
Callable<T> taskc = new Callable<T>(){
@Override
public T call() throws Exception{
//스레드가 처리할 작업 내용
return T;
}
}
작업처리요청
- ExecutorService의 작업큐에 Runnable 혹은 Callable객체를 넣는 행위!!
- 작업처리 요청을 위해 submit()과 execute() 메소드를 제공함.
- execute() : Runnable을 작업큐에 저장
- submit() : Runnable 또는 Callable을 작업큐에 저장, Future 객체를 리턴
- submit 메소드를 사용하는 것이 스레드의 생성오버헤드를 줄이는데 좋다. 왜냐하면 execute메소드는 작업처리중 예외가 발생하면 쓰던 스레드를 버리고 새로운 스레드를 생성한다. 하지만 submit 메소드는 쓰던 스레드를 재활용한다.
(이는 스레드이름을 통해 확인할 수 있다.)
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);//콘솔 출력시간을 위해 0.01초 일시정지
}
executorService.shutdown();
}