Spring高階話題-多執行緒-TaskExecutor
阿新 • • 發佈:2018-12-10
分析
在Spring中,通過任務執行器,也就是TaskExecutor來實現多執行緒和併發程式設計。
使用ThreadPoolTaskExecutor可實現一個基於執行緒池的TaskExecutor。 而實際開發中任務一般是非阻礙的,也就是非非同步的,所以我們要在配置類中通過@EnableAsync開啟對非同步任務的支援,並通過在實際執行的Bean的方法中使用@Async註解來宣告其是一個非同步任務。
示例
配置類
首先看一下配置類。 現在全部使用Java配置哦,不用xml了。
package cn.hncu.p3.p2_TaskExecutor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* Created with IntelliJ IDEA.
* User: 陳浩翔.
* Date: 2016/11/18.
* Time: 上午 9:35.
* Explain:配置類
*/
@Configuration
@ComponentScan("cn.hncu.p3.p2_TaskExecutor")
@EnableAsync //利用@EnableAsync註解開啟非同步任務支援
public class TaskExecutorConfig implements AsyncConfigurer{
//配置類實現AsyncConfigurer介面並重寫getAsyncExcutor方法,並返回一個ThreadPoolTaskExevutor
//這樣我們就獲得了一個基於執行緒池的TaskExecutor
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);//執行緒池維護執行緒的最少數量
taskExecutor.setMaxPoolSize(10);//執行緒池維護執行緒的最大數量
taskExecutor.setQueueCapacity(25);//執行緒池所使用的緩衝佇列
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
任務執行類
也就是實際執行的,需要非同步執行的類
package cn.hncu.p3.p2_TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* Created with IntelliJ IDEA.
* User: 陳浩翔.
* Date: 2016/11/18.
* Time: 上午 10:57.
* Explain:任務執行類
*/
@Service
public class AsyncTaskService {
@Async
//通過@Async註解表明該方法是個非同步方法,如果註解在類級別,則表明該類所有的方法都是非同步方法。
// 而這裡的方法自動被注入使用ThreadPoolTaskExecutor作為TaskExecutor
public void executeAsyncTask(Integer i){
System.out.println("executeAsyncTask:"+i);
}
@Async
public void executeAsyncTaskPlus(Integer i){
System.out.println("executeAsyncTaskPlus:"+i);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
執行類
為了測試而寫的執行呼叫方法的類
package cn.hncu.p3.p2_TaskExecutor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Created with IntelliJ IDEA.
* User: 陳浩翔.
* Date: 2016/11/18.
* Time: 上午 11:04.
* Explain:執行類
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
for(int i=0;i<10;i++){
asyncTaskService.executeAsyncTaskPlus(i);
asyncTaskService.executeAsyncTask(i+1);
}
context.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
執行結果
執行結果長了一點,所以只傳了這麼一點。 但是已經能夠看出了,假如是原來那樣的,是同步執行,那麼肯定偶數行的輸出比前一個奇數行的輸出是大1的。
結果不是那樣,它們是非同步進行的,在這裡由一個主執行緒(main執行緒)。 for迴圈裡面,每執行一行呼叫方法的,就會開一個執行緒。 也就是說,你每次的執行結果可能會不一樣! 所以,如果你的執行結果和我的不一樣,不要慌哦。
本文章由[諳憶]編寫, 所有權利保留。