스레드(thread) - (4)

김남건·2021년 8월 5일
0
post-thumbnail

스레드 풀 - Part 2

작업 생성

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 객체

Future는 작업 결과가 아닌 지연완료(Pending Completion) 객체이다. submit을 호출하면 즉시 반환되는 것이 Future 객체인데, 결과가 나올 때까지 기다렸다가(블로킹) 최종 결과를 얻기 위해 Future의 get()을 이용한다.

메서드설명
V get()작업이 완료될 때까지 블로킹 되었다가 처리 결과 V를 반환
V get(long timeout, TimeUnit unit)timout 시간동안 작업이 완료되면 V를 반환
작업이 완료되지 않으면 TimeoutException 발생시킴

메서드get 호출 시 반환 타입작업 처리 도중 예외발생
submit(Runnable task)nullfuture.get() -> 예외발생
submit(Runnable task, V result)V 값future.get() -> 예외발생
submit(Callabe<V> task)V 값future.get() -> 예외발생

예시1. submit(Runnable task)

Runnable task = new Runnable(){
    @Override
    public void run(){
        // 작업 내용
    }
}

Future future = executorService.submit(task);

try{
    future.get(); // 블로킹 상태
}catch(InterruptedException e){
    // 작업 처리 도중 스레드가 interrupt될 경우 실행
}catch(ExecutionException e){
    // 작업 처리 도중 예외 발생 시 실행
}

예시 2. submit(Callable<V> task)

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){
    // 작업 처리 도중 예외 발생 시 실행
}

예시 3. submit(Runnable task, V result)

작업 처리 결과를 외부 객체에 저장하는 방식이다. 보통 두 개 이상의 스레드 작업을 취합할 목적으로 사용한다.

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()작업 완료 여부 반환

작업 처리 중 예외 발생 시 동작

execute()

스레드가 종료되고 해당 스레드가 제거된다. 따라서 스레드 풀이 다른 작업을 처리하기 위해 새로운 스레드를 생성한다.

submit()

스레드가 종료되지 않고 다음 작업을 위해 재사용된다. 스레드 재생성 시 CPU가 관여하고 메모리도 다시 할당해야 하기 때문에 가급적 작업 처리 요청 시 submit을 사용할 것을 권장한다.

0개의 댓글

관련 채용 정보