實際開發自定義線程池的使用

實際開發過程中我們經常會用到線程池去執行一些任務,降低頻繁創建線程帶來的一些性能損耗,現將自己開發過程中自己定義的線程池分享給大家,希望能幫助到大家,同時歡迎大家進行評閱補充

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.PreDestroy;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class ExecutorPoolUtil {
    // 核心線程數
    public static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    // 最大線程數
    public static final int MAX_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    //
    public static final int KEEP_ALIVE_TIME = 60;
    // 最大阻塞隊列
    private static final int MAX_QUEUE = 200;

    private static ExecutorService executorService;
    // slfj 日誌
    private static final Logger logger = LoggerFactory.getLogger(ExecutorPoolUtil.class);

    static {
        logger.info("開始初始化線程池工具類,核心線程數:{},最大線程數:{},超出線程最大存活時間:{}s", CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME);
        executorService = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, new LinkedBlockingQueue<Runnable>(MAX_QUEUE),
                new ThreadFactory() {
                    // 記錄線程名稱,便於日誌排查問題
                    private final AtomicInteger threadNum = new AtomicInteger(1);

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = null;
                        try {
                            thread = new Thread(r);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        thread.setName("ExecutorPoolUtil-thread-" + threadNum);
                        thread.setDaemon(false);
                        thread.setPriority(Thread.NORM_PRIORITY);
                        return thread;
                    }
                }, );
        logger.info("初始化線程池結束");
    }

    // 對外提供獲得線程池對象方法
    public static ExecutorService getExecutorService() {
        return executorService;
    }

    public static void main(String[] args) {
        ThreadLocal threadLocal = new ThreadLocal();
    }

    // 工具類一般將空參構造私有化
    private ExecutorPoolUtil() {
    }

    // 對外提供工具類線程執行方法
    public static void execute(Runnable runnable) {
        Assert.notNull(runnable, "線程池初始化失敗,不能執行任務");
        logger.info("executorService.execute 開始執行線程");
        executorService.execute(runnable);
    }

    // 銷燬線程池對象
    @PreDestroy
    public void destory() {
        // 線程池拒絕接受新的任務,等待執行中的任務
        executorService.shutdown();
        while (true) {
            // 判斷執行中的任務是否結束
            if (executorService.isTerminated()) {
                logger.info("所有線程任務執行結束");
                break;
            }
            // 若任務未執行結束,線程sleep
            try {
                Thread.sleep(5l);
                logger.info("線程尚未執行結束,繼續等待。。。");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.error(e.getMessage(), e);
            }
        }
    }

    public static boolean isFull() {
        int activeCount = ((ThreadPoolExecutor) executorService).getActiveCount();
        if (MAX_POOL_SIZE == activeCount) {
            return true;
        }
        return false;
    }

    // 自定義拒絕策略(可以選擇默認等其他策略,根據業務需求定)
    private static class WaitPolicy implements RejectedExecutionHandler {
        private static final Logger logger = LoggerFactory.getLogger(WaitPolicy.class);

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

            try {
                executor.getQueue().offer(r, 60, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
                logger.error(e.getMessage(),e);
            }

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