1. 程式人生 > >Spring高階話題-多執行緒-TaskExecutor

Spring高階話題-多執行緒-TaskExecutor

分析

在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迴圈裡面,每執行一行呼叫方法的,就會開一個執行緒。 也就是說,你每次的執行結果可能會不一樣! 所以,如果你的執行結果和我的不一樣,不要慌哦。

本文章由[諳憶]編寫, 所有權利保留。