前言
本篇文章的代碼示例已放到 github 上,Git地址為:advance(記錄每一個學習過程),大家把代碼下載下來之後,全局搜索一些關鍵代碼,即可找到該文章的源碼。
大家覺得有用的話,麻煩點個star👍再走唄!
使用場景
當我們在使用SpringBoot進行開發的時候,可能會遇到一些執行異步任務的場景,如果每次執行這些異步任務都去新建一個異步線程來執行的話,那代碼就太冗餘了。幸好SpringBoot給我們提供了Async的註解,讓我們能夠很輕鬆地對這些異步任務進行執行。
使用示例
在啓動類上使用@EnableAsync註解,表示開啓異步任務
@EnableAsync
@SpringBootApplication
public class AsycnDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AsycnDemoApplication.class, args);
}
}
將需要執行的異步方法所在的類,加入到Spring的容器中,可以使用@Component註解
@Component
public class AsyncComponent {
}
在需要異步執行的方法上,加入@Async註解
@Component
public class AsyncComponent {
@Async
public void async(String str){
System.out.println("輸入的內容是" + str + ",異步任務正在休眠5秒..");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
System.out.println("休眠失敗");
}
System.out.println("輸入的內容是" + str + ",異步任務執行結束");
}
}
在其他需要調用的地方,將這個異步方法所在的類進行注入,然後調用
@Component
public class LineRunner implements CommandLineRunner {
@Autowired
private AsyncComponent asyncComponent;
@Override
public void run(String... args) throws Exception {
System.out.println("主線程開始");
asyncComponent.async("今天不上班,好耶");
asyncComponent.selfAsync();
System.out.println("主線程結束");
}
}
執行結果
自定義異步調用的線程池
SpringBoot默認會使用SimpleAsyncTaskExecutor線程池,這個不是真的線程池,不會重用線程,每次調用都會新建一個線程出來,用完之後就回收掉,沒起到重複利用的作用。併發量太大的話,可能會有內存溢出的風險。
因此,更加推薦開發者對異步調用的線程池進行自定義。
自定義異步線程池
@Configuration
public class ExecutorsAsyncConfig {
@Bean(name = "asyncConfig")
public Executor asyncConfig(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//設置核心線程數
executor.setCorePoolSize(5);
//設置最大線程數
executor.setMaxPoolSize(50);
//設置緩存的隊列
executor.setQueueCapacity(1000);
//設置空閒線程的超時時間
executor.setKeepAliveSeconds(1000 * 5);
//設置線程名稱的前綴
executor.setThreadNamePrefix("async-config-");
executor.initialize();
return executor;
}
}
編寫自定義的異步方法,其實也就就是在@Async的註解上加了線程池的bean名稱。
@Async("asyncConfig")
public void selfAsync(){
System.out.println("我是自定義異步線程,線程池名稱:" + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
System.out.println("休眠失敗");
}
System.out.println("自定義異步線程休眠結束");
}
調用自定義的異步方法
asyncComponent.selfAsync();
執行結果
Async失效場景(注意事項)
- 調用方法和異步方法在同一個類中,會導致Async失效。
- 異步方法使用了static進行修飾,會導致Async失效。