Spring/Spring

[Spring][Integration] 1. Task Execution: @Async

noahkim_ 2023. 10. 16. 02:16
  • Spring은 비동기 작업의 실행을 위한 인터페이스를 제공합니다.
  • Spring은 이러한 인터페이스를 구현하는 구현체도 제공합니다.
    • 스레드 풀을 지원하거나 애플리케이션 서버 환경 내에서의 CommonJ에 위임할 수 있습니다

 

1. The Spring TaskExecutor Abstraction

TaskExecutor Types

  • Spring은 다양한 요구 사항과 환경에 맞게 선택할 수 있는 다양한 TaskExecutor 구현체를 제공합니다.

 

SyncTaskExecutor
  • 호출을 비동기적으로 실행하지 않습니다.
    • 각 호출은 호출하는 쓰레드에서 직접 실행됩니다.
  • 주로 멀티 쓰레딩이 필요하지 않은 상황, 예를 들어 간단한 테스트 케이스에서 사용됩니다.

 

SimpleAsyncTaskExecutor
  • 이 구현체는 쓰레드를 재사용하지 않습니다.
  • 각 호출마다 새로운 쓰레드를 시작합니다.
  • 동시성 제한을 지원하여 제한을 초과하는 호출이 슬롯이 사용 가능해질 때까지 차단됩니다.

 

ConcurrentTaskExecutor
  • 이 구현체는 java.util.concurrent.Executor 인스턴스의 어댑터입니다.
  • ThreadPoolTaskExecutor는 Executor 구성 매개 변수를 bean 속성으로 노출하는 대안이 있습니다.
  • ConcurrentTaskExecutor를 직접 사용할 필요는 거의 없습니다.

 

ThreadPoolTaskExecutor
  • 이 구현체는 가장 일반적으로 사용됩니다.
  • java.util.concurrent.ThreadPoolExecutor를 구성하는 bean 속성을 노출하고 TaskExecutor로 감싸줍니다.
  • 다른 종류의 java.util.concurrent.Executor에 적응해야 한다면, ConcurrentTaskExecutor를 사용하는 것이 좋습니다.

 

2. Annotation Support for Scheduling and Asynchronous Execution

Enable Scheduling Annotations

  • Spring 프로젝트에서 비동기 작업 및 스케쥴링 작업을 쉽게 활성화하고 관리할 수 있게 도와줍니다.
  
@EnableAsync
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
  • 이 어노테이션을 사용하면 @Async 어노테이션을 사용한 메서드가 비동기적으로 실행될 수 있게 됩니다.
  • 즉, 메서드 호출이 즉시 반환되고, 실제 메서드 실행은 별도의 쓰레드에서 비동기적으로 수행됩니다.
  • 더 세밀한 제어가 필요한 경우 AsyncConfigurer 인터페이스를 구현할 수 있습니다.

 

The @Async annotation

기본사용
@Async
void doSomething() {
	// this will be run asynchronously
}
  • @Async 어노테이션을 메서드에 제공하면 그 메서드는 비동기적으로 호출됩니다.

 

인자가 있는 @Async
@Async
void doSomething(String s) {
	// this will be run asynchronously
}
  • @Async 어노테이션을 사용한 메서드는 인자를 가질 수 있습니다.
  • 이러한 메서드는 일반적인 방식으로 런타임에 호출자에 의해 호출됩니다.

 

반환이 있는 @Async
@Async
Future<String> returnSomething(int i) {
	// this will be run asynchronously
}
  • @Async 어노테이션을 사용하여 값 반환 메서드도 비동기적으로 호출할 수 있습니다.
  • 그러나 이러한 메서드는 Future 형식의 반환 값이 필요합니다.

 

주의사항
  • 라이프사이클 콜백과 함께 사용할 수 없습니다.
public class SampleBeanImpl implements SampleBean {

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

public class SampleBeanInitializer {
	private final SampleBean bean;

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

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

 

Executor Qualification with @Async

@Async("otherExecutor")
void doSomething(String s) {
	// this will be run asynchronously by "otherExecutor"
}
  • @Async를 메서드에 지정하면, 비동기 지원을 활성화할 때 구성된 실행자(executor)가 사용됩니다.
  • 기본 실행자가 아닌 다른 실행자를 사용하여 특정 메서드를 실행해야 할 때 value 속성을 사용하여 실행자를 지정할 수 있습니다.

 

Exception Management with @Async

@Async 어노테이션을 사용하여 메서드를 비동기적으로 실행할 때는 예외 처리에 주의해야 합니다.

 

Future-typed 반환 값이 있는 경우
  • 메서드 실행 중에 발생한 예외는 Future 결과에 대한 get을 호출할 때 발생합니다. 
  • try-catch 블록으로 쉽게 처리할 수 있습니다.

 

void 반환 타입인 경우
  • 예외는 캐치되지 않아 전달될 수 없습니다.
  • 이런 예외를 처리하기 위해 AsyncUncaughtExceptionHandler를 제공할 수 있습니다.

 

public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {

	@Override
	public void handleUncaughtException(Throwable ex, Method method, Object... params) {
		// handle exception
	}
}
  • AsyncUncaughtExceptionHandler를 구현하고 있으며, 비동기 메서드에서 캐치되지 않은 예외를 처리합니다.

 

설정

AsyncUncaughtExceptionHandler 정의
  • AsyncConfigurer
  • XML의 <task:annotation-driven/> 요소를 사용

 

 

 

출처