package com.gingersoft.gsa.cloud.common.utils.threadPool;

import android.util.Log;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 作者：ELEGANT_BIN
 * 版本：1.6.0
 * 创建日期：2019-11-18
 * 修订历史：2019-11-18
 * 描述： 線程池管理類
 */
public class ThreadPoolManager {

    private String TAG = this.getClass().getSimpleName();

    private static ThreadPoolManager instence = null;

    private ThreadPoolExecutor mThreadPoolExecutor;
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    //线程数量,核心线程数
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    //池中允许的最大线程数
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    //设置空闲线程的空闲时间，如果一共有6个线程，那么超出核心线程数的两个线程就会被记录时间，超过该时间就会被杀死，如果没有超过核心线程数，那么线程是不会被倒计时的。
    private static final int KEEP_ALIVE_SECONDS = 30;
    //等待执行的容器容量大小
    private int capacity = 128;
    //拒绝后的执行任务容器--》凉快的地方
    private LinkedBlockingQueue taskQueue = new LinkedBlockingQueue();

    public synchronized static ThreadPoolManager getInstence() {
        if (instence == null) {
            synchronized (ThreadPoolManager.class) {
                if (instence == instence) {
                    instence = new ThreadPoolManager();
                }
            }
        }
        return instence;
    }

    /**
     * 构造方法里面就初始化线程池
     * ArrayBlockingQueue是一个执行任务的容量，当调用mThreadPoolExecutor的execute，容量加1，执行run完后，容量减1
     * ArrayBlockingQueue后面传入true就是以FIFO规则存储：先进先出
     */
    public ThreadPoolManager() {
        if (mThreadPoolExecutor == null) {
            mThreadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(capacity, true), handler);
        }
        //开启线程一直循环从等待队列里面取出可执行任务并执行
        mThreadPoolExecutor.execute(runnable);
    }


    /**
     * 往队列里面存入可执行任务
     *
     * @param runnable
     */
    public void putExecutableTasks(Runnable runnable) {
        try {
            taskQueue.put(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * ThreadPoolExecutor的run
     */
    private Runnable runnable = new Runnable() {

        @Override
        public void run() {
            //开启循环
            while (true) {
                //取出等待的执行任务
                Runnable taskQueueRunnable = null;
                try {
                    Log.d(TAG, "等待队列大小：" + taskQueue.size());
                    taskQueueRunnable = (Runnable) taskQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (runnable != null) {
                    mThreadPoolExecutor.execute(taskQueueRunnable);
                }
                Log.d(TAG, "线程池大小" + mThreadPoolExecutor.getPoolSize());
            }
        }
    };

    /**
     * 拒绝策略
     * 当ArrayBlockingQueue容量过大，就要执行拒绝策略，对来的执行任务说：放不下了，先到一边凉快去，那么就要有一个凉快的容器装他们
     */
    private RejectedExecutionHandler handler = new RejectedExecutionHandler() {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                taskQueue.put(r);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    public ThreadPoolExecutor getExecutor() {
        return mThreadPoolExecutor;
    }
}

