package com.artfess.cqxy.utils;

import com.artfess.uc.exception.BaseException;

import java.util.Random;
import java.util.concurrent.*;

/**
 * @project: sym
 * @author: naf
 * @date: 2021-08-12 09:59
 * @desc: 多线程优化工具类
 **    int threadNum = ThreadUtil.getExpectThreadNum(taskNum);
 *    int threadTaskNum = ThreadUtil.getThreadTaskNum(threadNum, taskNum);
 *    ......根据以上参数创建线程......
 *
 **/
public class ThreadUtil {
    private static final int TASK_SIZE_1 = 20;
    private static final int TASK_SIZE_2 = 40;
    private static final int TASK_SIZE_3 = 80;
    private static final int TASK_SIZE_4 = 160;
    private static final int QUEUE_DEFAULT_WAIT_TIME = 30;


    public static ExecutorService publicPool;



    static {
        int poolSize = getCoreNum() * 2;
        int maxPoolSize = poolSize * 2;

        publicPool = new ThreadPoolExecutor(
                poolSize,
                maxPoolSize,
                QUEUE_DEFAULT_WAIT_TIME,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(maxPoolSize),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    /**
     * 获取服务器CPU核心数
     * @author naf
     * @return *
     */
    public static int getCoreNum() {
        return Runtime.getRuntime().availableProcessors();
    }

    /**
     * 计算需要开的线程数
     * @author naf
     * @return *
     */
    public static int getExpectThreadNum(int taskNum) {
        int coreNum = getCoreNum();
        if (taskNum <= 0) {
            throw new BaseException("多线程初始化异常: 任务数量为0");
        }
        //1线程
        if (taskNum == 1) {
            return 1;
        }
        //2线程
        else if (taskNum <= TASK_SIZE_1) {
            return Math.min(coreNum, 2);
        }
        //4线程
        else if (taskNum <= TASK_SIZE_2) {
            return Math.min(coreNum, 4);
        }
        //6线程
        else if (taskNum <= TASK_SIZE_3) {
            return Math.min(coreNum, 6);
        }
        //8线程
        else if (taskNum <= TASK_SIZE_4) {
            return Math.min(coreNum, 8);
        }
        //根据核心数计算
        else {
            return coreNum <= 8 ?
                    coreNum : coreNum <= 16 ?
                    (coreNum - 4) : 16;
        }
    }

    /**
     * 获取每个线程的任务数量
     * @author naf
     * @return *
     */
    public static int getThreadTaskNum(int threadNum, int taskNum) {
        if (threadNum > taskNum) {
            throw new BaseException("多线程初始化异常: 线程数>任务数");
        }
        return taskNum / threadNum;
    }

    /**
     * 自动任务执行前, 休眠一段时间, 减少压力
     * @param secondsBound 时间范围,单位秒
     * @author naf
     */
    public static void sleepBeforeAutoTask(int secondsBound) {
        secondsBound = secondsBound <= 0 ? 60 * 30 : secondsBound;

        Random random = new Random();
        int i = random.nextInt(secondsBound) + 1;
        try {
            TimeUnit.SECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 自动任务执行前, 休眠一段时间减少并发压力 (默认随机时间范围30分钟)
     * @author naf
     */
    public static void sleepBeforeAutoTask() {
        Random random = new Random();
        int i = random.nextInt(60 * 30) + 1;
        try {
            TimeUnit.SECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
