오늘도 개발자 Backend Developer

[Spring Async] 1. 비동기 처리를 해보자.

  • Spring에서 제공해주는 @Async Annotation을 사용하여 비동기처리를 한다.
  • 비동기로 실행하고, 결과값을 받아보자.
  • 비동기로 처리 중에 발생되는 문제(Exception)를 잡아서 처리하자.
  • 비동기 전송 방식이란?

@Async?

  • https://spring.io/guides/gs/async-method/

기본 사용법

@Async
public void run() {
}

제약사항

  • 리턴값은 void와 java.util.concurrent.Future만 사용가능하다.
  • public 메소드만 사용 가능하다.
  • 스스로를 호출하여 동작시킬 수 없다.(self-invocation)

설정하기

  • Spring Boot 기준으로 설명할 예정.

Dependency

spring-context 가 포함되어 있으면 됩니다.

Spring Configuration

  • annotation : @EnableAsync
  • 기본으로 설정되어 있는 TaskExecutorSimpleAsyncTaskExecutor 로 매번 Thread를 생성하여 Thread Pool이 아니다.

기본 설정 구조

@EnableAsync
@Configuration
public class AsyncConfiguration implements AsyncConfigurer {

}

공통된 Thread Pool을 사용하는 방법

  • AsyncConfigurer 를 implements 하여 getAsyncExecutor method를 override 한다.
@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

	@Override
	public Executor getAsyncExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setThreadNamePrefix("async-thread-");
		executor.setCorePoolSize(10);
		executor.setMaxPoolSize(50);
		executor.setQueueCapacity(100);
                executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); //추후 설명
		executor.initialize();
		return executor;
	}
}
  • 호출하는 법
@Async
public void taskExecutor() {
    log.info("thread run");
}

각각 다른 Thread Pool을 사용하는 방법

  • 사용할 각각의 TaskExecutor를 생성한다.
@Bean("taskExecutor_1")
public Executor taskExecutor_1() {
	ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
	executor.setThreadNamePrefix("each-async-thread-1-");
	executor.setCorePoolSize(10); 
	executor.setMaxPoolSize(50); 
	executor.setQueueCapacity(100); 
	executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
	return executor;
}

@Bean("taskExecutor_2")
public Executor taskExecutor_2() {
	ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
	executor.setThreadNamePrefix("each-async-thread-2-");
	executor.setCorePoolSize(10); 
	executor.setMaxPoolSize(50); 
	executor.setQueueCapacity(100);
	executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
	return executor;
}
  • 호출하는 법
@Async("taskExecutor_1")
public void taskExecutor1() {
    log.info("thread name : {} ", Thread.currentThread().getName());
}

@Async("taskExecutor_2")
public void taskExecutor2() {
    log.info("thread name : {} ", Thread.currentThread().getName());
}