스프링 프레임워크는 비동기 실행을 위하여 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@Async 는 라이프 사이클 콜백으로 연결되는 @PostConstruct 과 함께는 사용될 수 없다. 비동기 적으로 Spring Bean을 초기화 시키려면 아래와 같이 @Async와는 분리하여 실행시켜야 한다.returnSomething(int i) { // this will be executed asynchronously }
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
댓글 없음 :
댓글 쓰기