Runnable이나 Callable 인터페이스의 구현 객체로 표현한다. Runnable은 run 메서드의 반환값이 존재하지 않고, Callable은 존재한다. 스레드 풀의 스레드는 작업 큐에서 Runnable이나 Callable 객체를 가져와 run과 call 메서드를 실행하게 된다.
Runnable task = new Runnable(){
@Override
public void run(){
// 작업 내용
}
}
Callable<T> task = new Callable<T> {
@Override
public T call() throws Exception{
// 스레드가 처리할 작업 내용
return T;
}
}
ExecutorService의 작업 큐에 Runnable, Callable 객체를 넣는 것을 의미한다. 이를 위해 ExecutorService가 제공하는 메서드는 다음과 같다.
메서드 | 설명 |
---|---|
void execute(Runnable command) | Runnable 객체를 작업 큐에 저장한다. 작업 처리 결과를 받지 못한다. |
Future<?> submit(Runnable task) Future<V> submit(Runnable task, V result) Future<V> submit(Callable<V> task) | Runnable, Callable 객체를 작업 큐에 저장한다. 반환된 Future를 통해 작업 처리 결과를 얻을 수 있다. |
Future는 작업 결과가 아닌 지연완료(Pending Completion) 객체이다. submit을 호출하면 즉시 반환되는 것이 Future 객체인데, 결과가 나올 때까지 기다렸다가(블로킹) 최종 결과를 얻기 위해 Future의 get()을 이용한다.
메서드 | 설명 |
---|---|
V get() | 작업이 완료될 때까지 블로킹 되었다가 처리 결과 V를 반환 |
V get(long timeout, TimeUnit unit) | timout 시간동안 작업이 완료되면 V를 반환 작업이 완료되지 않으면 TimeoutException 발생시킴 |
메서드 | get 호출 시 반환 타입 | 작업 처리 도중 예외발생 |
---|---|---|
submit(Runnable task) | null | future.get() -> 예외발생 |
submit(Runnable task, V result) | V 값 | future.get() -> 예외발생 |
submit(Callabe<V> task) | V 값 | future.get() -> 예외발생 |
Runnable task = new Runnable(){
@Override
public void run(){
// 작업 내용
}
}
Future future = executorService.submit(task);
try{
future.get(); // 블로킹 상태
}catch(InterruptedException e){
// 작업 처리 도중 스레드가 interrupt될 경우 실행
}catch(ExecutionException e){
// 작업 처리 도중 예외 발생 시 실행
}
Callable<Integer> task = new Callable<Integer>(){
@Override
public T call throws Exception{
// 작업 코드
return T;
}
}
Future<Integer> future = executorService.submit(task);
try{
int result = future.get(); // 블로킹 상태
}catch(InterruptedException e){
// 작업 처리 도중 스레드가 interrupt될 경우 실행
}catch(ExecutionException e){
// 작업 처리 도중 예외 발생 시 실행
}
작업 처리 결과를 외부 객체에 저장하는 방식이다. 보통 두 개 이상의 스레드 작업을 취합할 목적으로 사용한다.
class Task implements Runnable{
Result result;
Task(Result result){
this.result = result;
}
@Override
public void run(){
// 작업코드
// 처리결과는 result에 저장
}
}
public static void main(){
Result result = ???;
Runnable task = new Task(result);
Future<Result> future = executorService.submit(task, result);
result = future.get();
}
메서드 | 설명 |
---|---|
boolean cancel(boolean myInterruptIfRunning) | 작업 처리가 진행중일 경우 취소시킴 |
boolean isCancelled() | 작업 취소 여부 반환 |
boolean isDone() | 작업 완료 여부 반환 |
스레드가 종료되고 해당 스레드가 제거된다. 따라서 스레드 풀이 다른 작업을 처리하기 위해 새로운 스레드를 생성한다.
스레드가 종료되지 않고 다음 작업을 위해 재사용된다. 스레드 재생성 시 CPU가 관여하고 메모리도 다시 할당해야 하기 때문에 가급적 작업 처리 요청 시 submit을 사용할 것을 권장한다.