package com.yeechart.dotMatrix.thread;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.TimeUnit;

@Configuration
public class ThreadPoolTaskExecutorConfig {

    private static final Logger log = LoggerFactory.getLogger(ThreadPoolTaskExecutorConfig.class);
    // 获取服务器的CPU核心数
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    // 核心线程数，基于CPU核心数的两倍，适合大多数并发场景
    private static final int CORE_POOL_SIZE =  (int) (CPU_COUNT * 1.5);//CPU_COUNT*2

    // 最大线程数，基于CPU核心数的四倍，适用于高并发短暂任务
    private static final int MAX_POOL_SIZE =  Math.max(4, (int) (CPU_COUNT * 3));//CPU_COUNT*4

    // 队列容量，设置为最大线程数的两倍，以平衡内存使用和任务排队，避免无界队列导致的内存溢出
    private static final int QUEUE_CAPACITY = MAX_POOL_SIZE * 2;

    // 空闲线程存活时间，单位秒，这里设置为60秒
    private static final int KEEP_ALIVE_SECONDS = 30;//


    @Autowired
    private RetryService retryService;

    @Bean(name="voiceThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor voiceThreadPoolTaskExecutor(){
        ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();

        // 设置核心线程数
        poolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        // 设置最大线程数
        poolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        // 使用有界队列，避免内存无限增长
        poolTaskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        // 空闲线程存活时间
        poolTaskExecutor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        // 当线程池关闭时等待所有任务完成
        poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池中任务的等待时间，如果超过这个时间还没有销毁就强制销毁，以确保应用最后能够被关闭，而不是阻塞住
        poolTaskExecutor.setAwaitTerminationSeconds(60);
        // 设置线程前缀，便于定位
        poolTaskExecutor.setThreadNamePrefix("voiceThreadPool-");
        // 自定义拒绝策略
        poolTaskExecutor.setRejectedExecutionHandler((r, executor1) -> {
            log.error("线程池已满，任务被拒绝，正在重新进入拒绝策略：{}", r.toString());
            RetryService.TaskSubmitCallback callback = () -> retryService.cancelRetry(r);
            retryService.scheduleRetry(r, 1,  TimeUnit.SECONDS,  callback);
        });

        // 初始化线程池
        poolTaskExecutor.initialize();

        return poolTaskExecutor;
    }
}