1. pom文件里依賴這個包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.應(yīng)用啟動類添加@EnableAsync注解
@SpringBootApplication
@EnableAsync
public class SpringBootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStudyApplication.class);
}
}
3.配置異步任務(wù)線程池
由于默認的異步任務(wù)會開啟始終會一個新的線程拗胜,不利于資源的重復(fù)利用灵汪,所以檀训,要編寫一個異步任務(wù)的線程池
//AsyncPoolConfig.java
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
private final Logger logger = LoggerFactory.getLogger(MyAsyncTask.class);
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);// 設(shè)置核心線程池線程的數(shù)量,默認是1
executor.setMaxPoolSize(20); // 線程池最大的線程數(shù)量享言,當(dāng)核心線程都被用光峻凫,且緩沖隊列是滿的之后才申請
executor.setQueueCapacity(20); // 緩沖隊列中任務(wù)的個數(shù)
executor.setKeepAliveSeconds(60); // 超出核心線程數(shù)的其他線程在空閑時的最大的存活時間
executor.setThreadNamePrefix("frank_"); //線程池中的線程名稱前綴
executor.setWaitForTasksToCompleteOnShutdown(true);//程序關(guān)閉后,是否等待異步任務(wù)完成, 等待的時間需要配置览露, 默認false荧琼,
executor.setAwaitTerminationSeconds(60);// 等待的時間,默認0
//拒絕策略 線程池中的最大線程線程數(shù)用光,且緩沖隊列也滿了命锄,可以選擇的策略
// DiscardPolicy: 丟棄需要添加的新的任務(wù)
// AbortPolicy: 直接拋出異常
// DiscardOldestPolicy: 丟棄阻塞隊列的隊頭任務(wù)
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return executor;
}
//異步任務(wù)異常處理類,只會處理沒有返回值的異步任務(wù)的異常
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler{
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
logger.info("AsyncException:{}, Method:{}, Params:{}", throwable, method, objects);
throwable.printStackTrace();
//TODO 發(fā)送郵件或者短信
}
}
}
4.編寫異步任務(wù)
@Component
public class MyAsyncTask {
private final Logger logger = LoggerFactory.getLogger(MyAsyncTask.class);
@Async("getAsyncExecutor")
public void asyncProcess() throws InterruptedException {
logger.info("async process task, current thread name -> {}", Thread.currentThread().getName());
Thread.sleep(10000);
//int a = 1/0;
}
@Async("getAsyncExecutor")
public Future<Integer> asyncProcessHasReturn() throws InterruptedException {
logger.info("async process task(has return), current thread name -> {}", Thread.currentThread().getName());
Thread.sleep(10000);
//int a = 1/0;
return new AsyncResult<>(100);
}
}
5.使用
@Autowired
private MyAsyncTask myAsyncTask;
logger.info("current thread name:", Thread.currentThread().getName());
myAsyncTask.asyncProcess();
Future<Integer> result = myAsyncTask.asyncProcessHasReturn();
logger.info("reuslt:{}", result.get(1, TimeUnit.SECONDS));//1s后定時任務(wù)沒執(zhí)行完就拋異常