Spring異步線程池

在Spring中存在一個AsyncConfigurer接口,它是一個可以配置異步線程池的接口,實現源碼如下:

package org.springframework.scheduling.annotation;

import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.lang.Nullable;

public interface AsyncConfigurer {

	/**
	 * The {@link Executor} instance to be used when processing async
	 * method invocations.
	 */
	@Nullable
	default Executor getAsyncExecutor() {
		return null;
	}

	/**
	 * The {@link AsyncUncaughtExceptionHandler} instance to be used
	 * when an exception is thrown during an asynchronous method execution
	 * with {@code void} return type.
	 */
	@Nullable
	default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return null;
	}

}

代碼比較簡單,其中getAsyncExecutor方法返回的是一個自定義線程池,這樣在開啓異步時,線程池就會提供空閒線程來執行異步任務。因爲線程中的業務邏輯可能拋出異常,所以還有一個處理異常的處理器方法。爲了使得異步可用,Spring還提供了註解@EnableAsync,如果Java配置文件標註它,那麼Spring就會開啓異步可用,這樣就可以使用註解@Async驅動Spring使用異步調用。下面我們看一下異步實例的實現代碼:

package com.martin.config.other.async;

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;

/**
 * @author: martin
 * @date: 2020/2/5
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    //定義線程池
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        //核心線程數
        poolExecutor.setCorePoolSize(10);
        //線程池最大線程數
        poolExecutor.setMaxPoolSize(30);
        //線程隊列最大線程數
        poolExecutor.setQueueCapacity(2000);
        //初始化
        poolExecutor.initialize();
        return poolExecutor;
    }
}

代碼中註解@EnableAsync表示開啓Spring異步,並通過覆蓋getAsyncExecutor方法,自定義一個線程池。這樣就可以在業務代碼中通過@Async註解使用該線程池執行異步操作。下面定義一個異步服務接口:

package com.martin.config.other.async;

/**
 * @author: martin
 * @date: 2020/2/5
 */
public interface AsyncService {
    void generateReport();
}



package com.martin.config.other.async;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @author: martin
 * @date: 2020/2/5
 */
@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService {
    @Override
    @Async //聲明使用異步調用
    public void generateReport() {
        log.error("報表生成線程名稱:{}", Thread.currentThread().getName());
    }
}

這個方法比較簡單,打印出了當前運行線程的名稱,以便後續驗證。需要注意的是這裏使用了@Async註解,這樣改方法在被調用的時候,它就會使用線程池的線程去執行它。啓動服務後,日誌打印如下:

報表生成線程名稱:ThreadPoolTaskExecutor-3
報表生成線程名稱:ThreadPoolTaskExecutor-4

 

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