spring註解詳解與用法(4)異步相關

 

導航:更多的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也不一樣

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章