2015년 12월 8일 화요일

Asynchronous Task Execution

1.소개
스프링 프레임워크는 비동기 실행을 위하여 TaskExecutor 인터페이스를 통한 추상화를 제공한다.

2. TaskExecutor types

Spring의 배포 버전에는 이미 TaskExecutor의 몇몇 구현체가 존재하기 때문에 당신은 스스로 구현하지 않아도 된다.

-SimpleAsyncTaskExecutor
이 구현체는 어떠한 스레드도 재활용하지않고, 새로운 실행이 있을 때마다 새로운 스레드를 시작한다.
하지만, 동시 실행하는 스레드의 갯수 제한은 존재한다. 만약 당신이 진정한 스레드 풀링을 찾고 있다면,
아래의 SimpleThreadPoolTaskExecutor 와 ThreadPoolTaskExecutor 을 살펴보길 바란다.

-SyncTaskExecutor
이 구현체는 비동기 실행을 하지않는다. 대신 각각의 실행할 task들은 호출되는 하나의 스레드 안에서 실행된다.
이 구현체는 멀티 스레드가 필요치 않는 간단한 test case등에서 사용된다.

-ConcurrentTaskExecutor
이 구현체는 java.util.concurrent.Executor 의 개조판이다. 그리고 ThreadPoolTaskExecutor 의 대체용이다.
이것은 Executor 설정을 bean의 properties로서 드러낸다. ConcurrentTaskExecutor 이 필요한 경우는 드물지만,
만약 당신이 쓰기에 ThreadPoolTaskExecutor 의 설정이 유연하지 않다면, 대체할 것으로 ConcurrentTaskExecutor 을
사용할 수 있다.

-SimpleThreadPoolTaskExecutor
이 구현체는 실제적으로 Quartz의 SimpleThreadPool의 서브클래스이다. 이 것은 Quartz와 Non-Quartz component의 공유가
필요한 경우에 사용된다.

- ThreadPoolTaskExecutor
이 구현체는 가장 흔히 사용되는 것 중 하나이다. 이 것은 java.util.concurrent.ThreadPoolExecutor 를 설정하기 위해,
properties를 노출하고, TaskExecutor로 감싸서 사용할 수 있다. 만약 당신이 다른 종류의 java.util.concurrent.Executor 를
사용해야 한다면, 대신 ConcurrentTaskExecutor 를 사용하기를 추천한다.

2.2 Using a TaskExecutor

스프링의 TaskExecutor 구현은 자바빈으로써 사용된다. 아래 예제에서는 ThreadPoolTaskExecutor 를 사용하여, 비동기로
메세지를 출력하고 있다.

import org.springframework.core.task.TaskExecutor;

public class TaskExecutorExample {

    private class MessagePrinterTask implements Runnable {

        private String message;

        public MessagePrinterTask(String message) {
            this.message = message;
        }

        public void run() {
            System.out.println(message);
        }

    }

    private TaskExecutor taskExecutor;

    public TaskExecutorExample(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    public void printMessages() {
        for(int i = 0; i < 25; i++) {
            taskExecutor.execute(new MessagePrinterTask("Message" + i));
        }
    }

}

위에서 본대로 당신은 스레드 풀에서 스레드를 검색하여 스스로 실행하기 보다는, 큐에 Runnable을 추가하고, TaskExecutor는 내부의 규칙에 따라 Task를 실행하게 된다. 아래에서 TaskExecutor의 설정에 대해 볼수 있다.

    
    
    



      
2.3 The @Async Annotation
메서드의 비동기 실행을 위해 @Async 어노테이션은 제공된다.
@Async
void doSomething() {
    // this will be executed asynchronously
}
이 메서드는 또한, argument를 받을 수 있다.
@Async
void doSomething(String s) {
    // this will be executed asynchronously
}
또한, Future 타입으로 결과 값을 return 받을 수도 있다. 이를 통해 이 메서드가 비동기적으로 실행되는 동안, 당신은 다른 task를 실행하고 이후에, get()을 통해 결과 값을 받을 수 있다.
@Async
Future returnSomething(int i) {
    // this will be executed asynchronously
}
@Async 는 라이프 사이클 콜백으로 연결되는 @PostConstruct 과 함께는 사용될 수 없다. 비동기 적으로 Spring Bean을 초기화 시키려면 아래와 같이 @Async와는 분리하여 실행시켜야 한다.
public class SampleBeanImpl implements SampleBean {

    @Async
    void doSomething() {
        // ...
    }

}

public class SampleBeanInititalizer {

    private final SampleBean bean;

    public SampleBeanInitializer(SampleBean bean) {
        this.bean = bean;
    }

    @PostConstruct
    public void initialize() {
        bean.doSomething();
    }

}
2.4 Executor qualification with @Async
기본적으로 @Async 가 선언된 메서드는, annotation-driven 을 통해 선언되어 있는 executor를 통해 실행된다. 하지만 @Async 어노테이션의 value 를 통해 특정한 메서드가 실행될 때 특정 executor를 지정할 수 있다.
@Async("otherExecutor")
void doSomething(String s) {
    // this will be executed asynchronously by "otherExecutor"
}

2.5 Exception management with @Async
@Async 메서드는 Future 타입의 return 값을 가지고 있기 때문에 get 메서드를 부를 때의 Future 결과 속의 exception을 처리하기가 쉽다. 하지만 void 와 같은 return 타입에서는 exception이 잡히지않고 전달되지않는다. 이런 경우, exception을 처리하기 위해서 AsyncUncaughtExceptionHandler 가 제공된다.
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {

    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        // handle exception
    }
}


기본적으로 exception은 로깅된다. 커스톰된 AsyncUncaughtExceptionHandler 는 AsyncConfigurer 또는 xml 설정 값인 task:annotation-driven 을
통해 정의될 수 있다.

원본 출처 : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

댓글 없음 :

댓글 쓰기