Springのアノテーション(@Async)で非同期を使う

Springで非同期処理を簡単に使う方法のメモ

参考はこちら -> Spring MVC(+Spring Boot)上での非同期リクエストを理解する

Springデフォルトの非同期

Springは起動クラスにアノテーションをつけるだけで、非同期処理ができる

@EnableAsyncを起動クラスに追加する

Application.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAutoConfiguration
@EnableAsync // <- これ追加する
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

}

これだけで、非同期のアノテーション(@Async)が使えるようになります。

@Asyncをつけたテキトーなクラスを作ってみます
SampleService.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@Async
public class TopServiceImpl {

    public String index() {

        try {
            for (int i = 0; i < 1000; i++) {
                Thread.sleep(10);
                log.info("{}",i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

下記のようにログがでてきました

2018-01-08 23:35:24.508  INFO 20519 --- [cTaskExecutor-1] com.tasktalk.service.TopServiceImpl      : 0

cTaskExecutor-1がでてきて、呼び出し回数ごとにこのスレッドが増えていきます。
これだけだと、スレッド数を管理できません。

スレッド数をSpringで管理する

WebMvcConfigurerAdapterを継承したクラスでメソッド2つ追加する

WebMvcConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@ComponentScan
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {  // <- このメソッド追加
        configurer.setTaskExecutor(taskExecutor());
    }

    @Bean
    public AsyncTaskExecutor taskExecutor(){ // <- このメソッド追加
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(10);
        return executor;
    }
}

下記のようにログがでてきました

2018-01-08 23:30:53.612  INFO 20519 --- [ taskExecutor-1] com.tasktalk.service.TopServiceImpl      : 149

taskExecutor-1と表記されていて、設定したスレッドプールから使用されております。