목차

Spring @Async

설정

@EnableAsync
public class SpringAsyncConfig extends AsyncConfigurerSupport {
 
    // 기본 taskExecutor 
    @Bean // @Bean 필수
    @Override
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor(); // 객체 설정해줄것.
    }
 
}

ThreadPoolTaskExecutor 설정

Cached Thread Pool 효과

ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("XXXX-");
threadPoolTaskExecutor.setCorePoolSize(0);
threadPoolTaskExecutor.setMaxPoolSize(Integer.MAX_VALUE);
threadPoolTaskExecutor.setQueueCapacity(0);
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setAwaitTerminationSeconds(15);

MDC 사용하기

ThreadPoolTaskExecutor 설정에 Decorator 지정

@Override
public Executor getAsyncExecutor() {
  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  executor.setTaskDecorator(new MdcTaskDecorator());
  executor.initialize();
  return executor;
}

MdcTaskDecorator.java

class MdcTaskDecorator implements TaskDecorator {
 
  @Override
  public Runnable decorate(Runnable runnable) {
    // Right now: Web thread context !
    // (Grab the current thread MDC data)
    Map<String, String> contextMap = MDC.getCopyOfContextMap();
    return () -> {
      try {
        // Right now: @Async thread context !
        // (Restore the Web thread context's MDC data)
        if (contextMap != null) {
            MDC.setContextMap(contextMap);
        }
 
        runnable.run();
      } finally {
        MDC.clear();
      }
    };
  }
}

CompletableFuture 지원

@Async
public CompletableFuture<User> findUser(String user) throws InterruptedException {
    logger.info("Looking up " + user);
    String url = String.format("https://api.github.com/users/%s", user);
    User results = restTemplate.getForObject(url, User.class);
    Thread.sleep(1000L);
    return CompletableFuture.completedFuture(results); //IT IS completedFuture
}