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

【Spring】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; } }

任務執行類

也就是實際執行的,需要非同步執行的類

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);
    }

}

執行類

為了測試而寫的執行呼叫方法的類

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的。

結果不是那樣,它們是非同步進行的,在這裡由一個主執行緒(main執行緒)。
for迴圈裡面,每執行一行呼叫方法的,就會開一個執行緒。
也就是說,你每次的執行結果可能會不一樣!
所以,如果你的執行結果和我的不一樣,不要慌哦。

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