工做中常常涉及異步任務,一般是使用多線程技術,好比線程池ThreadPoolExecutor,它的執行規則以下:html
在Springboot中對其進行了簡化處理,只須要配置一個類型爲java.util.concurrent.TaskExecutor或其子類的bean,並在配置類或直接在程序入口類上聲明註解@EnableAsync
。java
調用也簡單,在由Spring管理的對象的方法上標註註解@Async
,顯式調用便可生效。spring
通常使用Spring提供的ThreadPoolTaskExecutor類。springboot
@Configuration @EnableAsync public class BeanConfig { @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 設置核心線程數 executor.setCorePoolSize(5); // 設置最大線程數 executor.setMaxPoolSize(10); // 設置隊列容量 executor.setQueueCapacity(20); // 設置線程活躍時間(秒) executor.setKeepAliveSeconds(60); // 設置默認線程名稱 executor.setThreadNamePrefix("hello-"); // 設置拒絕策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待全部任務結束後再關閉線程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } }
@Component public class Hello { @Async public void sayHello(String name) { LoggerFactory.getLogger(Hello.class).info(name + ":Hello World!"); } }
從打印日誌中能夠看出線程池已經正常工做了。多線程
有時候咱們不止但願異步執行任務,還但願任務執行完成後會有一個返回值,在java中提供了Future泛型接口,用來接收任務執行結果,springboot也提供了此類支持,使用實現了ListenableFuture接口的類如AsyncResult來做爲返回值的載體。好比上例中,咱們但願返回一個類型爲String類型的值,能夠將返回值改造爲:異步
@Async public ListenableFuture<String> sayHello(String name) { String res = name + ":Hello World!"; LoggerFactory.getLogger(Hello.class).info(res); return new AsyncResult<>(res); }
調用返回值:測試
@Autowired private Hello hello; // 阻塞調用 hello.sayHello("yan").get(); // 限時調用 hello.sayHello("yan").get(1, TimeUnit.SECONDS)
@Async
還有一個參數,經過Bean名稱來指定調用的線程池-好比上例中設置的線程池參數不知足業務需求,能夠另外定義合適的線程池,調用時指明使用這個線程池-缺省時springboot會優先使用名稱爲'taskExecutor'的線程池,若是沒有找到,纔會使用其餘類型爲TaskExecutor或其子類的線程池。