package com.yifu.cloud.plus.v1.yifu.common.core.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
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;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步线程池
 * @Author fxj
 * @Date 2021-05-20
 * @return
 **/
@Configuration
@EnableAsync
@Slf4j
public class AsyncConfig implements AsyncConfigurer {

    // todo 幂等性如何保证
    @Override
    public Executor getAsyncExecutor() {
        //定义线程池
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        /**
         * <!-- 设置allowCoreThreadTimeout=true（默认false）时，核心线程会超时关闭 -->
         */
        taskExecutor.setAllowCoreThreadTimeOut(true);
        /**
         * 核心线程数
         * 1）<!-- 线程池维护线程的最少数量，即使没有任务需要执行，也会一直存活 -->
         * 2）<!-- 设置allowCoreThreadTimeout=true（默认false）时，核心线程会超时关闭 -->
         */
        taskExecutor.setCorePoolSize(2);
        /**
         * <!-- 允许的空闲时间，当线程空闲时间达到keepAliveTime时，线程会退出，直到线程数量=corePoolSize -->
         * <!-- 如果allowCoreThreadTimeout=true，则会直到线程数量=0 -->
         */
        taskExecutor.setKeepAliveSeconds(200);
        /**
         * <!-- 线程池维护线程的最大数量 -->
         * <!-- 当线程数>=corePoolSize，且任务队列已满时。线程池会创建新线程来处理任务 -->
         * <!-- 当线程数=maxPoolSize，且任务队列已满时，线程池会拒绝处理任务而抛出异常，异常见下
         */
        taskExecutor.setMaxPoolSize(5);
        /**
         * <!-- 缓存队列（阻塞队列）当核心线程数达到最大时，新任务会放在队列中排队等待执行 -->
         */
        taskExecutor.setQueueCapacity(100);
        /**
         * 建议配置threadNamePrefix属性，出问题时可以更方便的进行排查。
         **/
        taskExecutor.setThreadNamePrefix("HRO_TO_EKP_EXECUTOR");
        // 捕捉线程队列满的 拒绝处理
		taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
       /* taskExecutor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {
            log.error("当前任务线程池队列已满.");

        });*/
        //初始化
        taskExecutor.initialize();
        return taskExecutor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}
