導航:更多的spring註解標籤點擊這裏
@EnableAsync
開啓異步任務支持。註解在配置類上,這個沒什麼好說的
,可能有的人會問,開啓一個子線程的話,我們通過new Thread 或者實現runnable就可以了,爲什麼要用到這裏
其實一般情況下也是如果
EnableAsync是可以提供線程池的,我們需要實現AsyncConfigurer接口才有意義,如果不實現的話那麼就和new Thread或者實現runnable接口一樣的
使用示例:
@EnableAsync
public class Test implements AsyncConfigurer {
}
我們來看一下AsyncConfigurer 接口的源碼
如上圖所示,他只提供了2個方法
getAsyncExecutor方法是執行方法,返回線程池的一些信息, getAsyncUncaughtExceptionHandler則是發生了異常應該處理的方方法 具體配置如下所示:
@EnableAsync
public class Test implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
// TODO Auto-generated method stub
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心線程池數量,方法: 返回可用處理器的Java虛擬機的數量。
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
//最大線程數量
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors()*5);
//線程池的隊列容量
executor.setQueueCapacity(Runtime.getRuntime().availableProcessors()*2);
//線程名稱的前綴
executor.setThreadNamePrefix("this-excutor-");
// setRejectedExecutionHandler:當pool已經達到max size的時候,如何處理新任務
// CallerRunsPolicy:不在新線程中執行任務,而是由調用者所在的線程來執行
//executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
/*異步任務中異常處理*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
由於代碼中註釋已經很詳細了,這裏我就不再次闡述了
@Async
註解在方法上標示這是一個異步方法,在類上標示這個類所有的方法都是異步方法,執行線程池就是我們上面配置的
這個也沒有什麼好說的,使用如下所示
@Component
public class TreadTasks {
@Async
public void startMyTreadTask() {
System.out.println("這是一個異步線程");
}
}
使用也很簡單,如下所示
@RestController
public class Web {
@Autowired
private TreadTasks treadTasks;
@RequestMapping("a123")
public String aaa(){
treadTasks.startMyTreadTask();
return "111111";
}
}
執行效果如下所示
這個線程池是不是非常簡單?
確實是很簡單,網上絕大部分都是這麼說的,但是呢,這裏面有一個有意思的問題,那就是這麼做其實是錯誤的
這樣寫並不是一個異步線程,而是同一個線程,下面我們就來證明一下這個錯誤,我們修改一下代碼,如下所示
運行測試一下
我們可以看到,兩個線程的id是一模一樣的,根本就不是一個異步線程,如果還不信的話我們看看下面的代碼
加了一個打印語句
線程等待一會在執行
我們可以看到,虛擬機數量那一句根本沒有打印,而且先打印了異步線程id,說明這並不是一個異步。
那麼到底是怎麼回事呢?spring提供的有問題?
當然不是,因爲EnableAsync標籤根本就不是一個全局的標籤,他和@RestController類似,只是表明本類而已,所以我們需要把EnableAsync放到具體的類上纔是一個正確的異步,如下所示
而且線程池需要的標籤也不是EnableAsync,而是Component
這樣纔是正確的,執行效果如下所示
我們可以看到,打印了虛擬機的數量,而且兩個線程的id也不一樣