關於SpringBoot的異步任務使用

在SpringBoot中提供了異步任務的功能特性。

1.引入spring-boot-starter-web依賴

2.在Application啓動類上標註@EnableAsync註解

3.編寫異步方法:

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

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 異步處理服務
 */
@Slf4j
@Service
public class AsyncService {

    @Async("getAsyncExecutor")
    public void asyncProcess() throws InterruptedException {

        log.info("async process task, current thread name -> {}",
                Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(2);
    }

    @Async("getAsyncExecutor")
    public Future<Integer> asyncProcessHasReturn() throws InterruptedException {

        log.info("async process task (has return), current thread name -> {}",
                Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(2);
        return new AsyncResult<>(100);
    }
}

 此異步任務服務中定義了一個無返回值的異步方法,一個有返回值的方法。異步任務方法上須標註@Async註解,通過@Async指定使用的異步線程池。

 

4.自定義異步線程池 

默認情況下,springboot異步線程池特別簡單,使得線程不能被重新利用。每次調用方法時都會重新創建線程。

因此需要對異步線程池做自定義配置:

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;

/**
 * <h1>自定義異步線程池的配置</h1>
 */
@Slf4j
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {

}
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * <h1>自定義異步線程池的配置</h1>
 * 使用@Configuration標註配置類
 * 須繼承AsyncConfigurer接口
 */
@Slf4j
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
   
     /**
     * 獲取自定義的ThreadPoolExcutor
     * 使用@Bean將其注入spring容器中
     * */
    @Bean
    @Override
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setCorePoolSize(10);//線程池核心線程的數量
        executor.setMaxPoolSize(20);//線程池維護線程的最大數量
        executor.setQueueCapacity(20);//緩衝隊列任務的個數
        executor.setKeepAliveSeconds(60);//超出核心線程數的線程最大存活時間
        executor.setThreadNamePrefix("ImoocAsync_");

        executor.setWaitForTasksToCompleteOnShutdown(true);//是否等待所有線程執行完畢後才關閉線程池
        executor.setAwaitTerminationSeconds(60);//要關閉的等待時長,與上句一起生效

        // 拒絕策略
        executor.setRejectedExecutionHandler(
                new ThreadPoolExecutor.AbortPolicy()
        );

        executor.initialize();

        return executor;
    }

    /**
     * <h2>定義異步任務異常處理類</h2>
     * 返回自定義的AsyncExceptionHandler對象用作異常處理器
     * */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncExceptionHandler();
    }

    /**
     * 自定義異常處理器 包含異常處理邏輯
     */
    class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

        @Override
        public void handleUncaughtException(Throwable throwable,
                                            Method method, Object... objects) {
            log.info("AsyncError: {}, Method: {}, Param: {}",
                    throwable.getMessage(),
                    method.getName(),
                    JSON.toJSONString(objects));
            throwable.printStackTrace();

            // TODO 發送郵件或者短信
        }
    }
}

 

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