8

I have a Spring Boot application which is responsible for answering requests via REST. I also push metrics about my application call. Since this is a separate task and I have to response users immediately, I want to make that metrics publishing asynchronously. So I've used that:

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("MyApp-");
executor.initialize();
return executor;

However, this one uses SimpleAsyncTaskExecutor and does not reuse any threads.

1) How can I use ConcurrentTaskExecutor instead of SimpleAsyncTaskExecutor?

2) Which implementation could best fit for my needs?

1
  • 1
    ThreadPoolTaskExecutor does not use SimpleAsyncTaskExecutor, it uses Java's standard ThreadPoolExecutor (see the implementation). So you are already sort of using the ConcurrentTaskExecutor. Commented Dec 11, 2016 at 23:46

2 Answers 2

10

To make your custom Executor work, make sure it's registered as a Bean, and reference it on the method annotated with @Async:

@Bean(name = "transcodingPoolTaskExecutor")
public Executor transcodingPoolTaskExecutor() {
    final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix("transcoder-");
    executor.initialize();
    return executor;
}

And in the @Service which is holding the method:

@Async("transcodingPoolTaskExecutor")
public void transcodeVideo(UUID fileId) {
    mediaFileService.transcodeVideo(fileId);
}
Sign up to request clarification or add additional context in comments.

1 Comment

You should not call executor.initialize(), because it's called by Spring through InitializingBean.afterPropertiesSet().
2

You can also redefine the default executor by creating a Configuration class which implements AsyncConfigurer. Something like this:

@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
    @Value("${async.executor.corePoolSize:20}")
    private int corePoolSize;

    @Value("${async.executor.maxPoolSize:100}")
    private int maxPoolSize;

    @Value("${async.executor.queueCapacity:50}")
    private int queueCapacity;

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("Async Executor -");
        executor.initialize();
        return executor;
    }
}

In this case you wouldn't need to specify the executor name in @Async annotation. Spring will take executor, which you defined in AsyncConfig.

It's very similar to the solution provided by yglodt, but in this case you don't need to specify the name of executor in every @Async annotation, so it removes potential misspelling in the executor name.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.