juc - 線程池的使用

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @description: 測試使用線程池
 */
public class TestThreadPool {

    public static void main(String[] args) {
        //核心線程個數
        int corePoolSize = 2;
        //最大線程數量
        int maximumPoolSize = 4;
        //創(chuàng)建了超出核心線程個數的線程(臨時線程)后,當該線程空閑下來可能會被銷毀
        //線程允許空閑時間(線程在空閑狀態(tài)下,在允許空閑時間內不會銷毀)
        //TimeUnit表示允許線程空閑時間的單位
        long keepAliveTime = 1L;
        //等待隊列
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1024);
        //線程池飽和策略
        RejectedExecutionHandler policy = new RejectedDiscardPolicy("taskId");
        ExecutorService executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, queue, policy);
        for (int i = 0; i < 100000; i++) {
            executor.execute(new Worker());
        }

        //慎用shutdownNow(立即關閉線程池,不管隊列中的任務是否執(zhí)行完)
//      executorService.shutdownNow();
        //推薦使用shutdown去關閉線程池,這個方法會等待隊列中的任務全部執(zhí)行完才去關閉線程池
        executor.shutdown();
    }


}

class Worker implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在執(zhí)行");
    }
}


/**
 * @description: 自定義飽和策略(中止策略也是默認策略)
 */
class RejectedAbortPolicy implements RejectedExecutionHandler {
    /**
     * 執(zhí)行任務的標識
     */
    private String taskId;

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public RejectedAbortPolicy(String taskId) {
        this.taskId = taskId;
    }

    /**
     * @description: 使用該策略時在飽和時會拋出RejectedExecutionException(繼承自RuntimeException),調用者可捕獲該異常自行處理。
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        throw new RejectedExecutionException(taskId +
                " rejected from " +
                executor.toString());
    }
}

/**
 * @description: 自定義飽和策略(拋棄策略)
 */
class RejectedDiscardPolicy implements RejectedExecutionHandler {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 執(zhí)行任務的標識
     */
    private String taskId;

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public RejectedDiscardPolicy(String taskId) {
        this.taskId = taskId;
    }

    /**
     * @description: 不做任何處理直接拋棄任務
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        //計劃執(zhí)行的大致任務數
        String taskCount = String.valueOf(executor.getTaskCount());
        //正在執(zhí)行任務的大致線程數
        String activeCount = String.valueOf(executor.getActiveCount());
        //不處理使用拋棄策略
        logger.error("RejectedDiscardPolicy.rejectedExecution, taskId :{}, task count: {}, active thread: {}", taskId,
                taskCount, activeCount);
    }

}

/**
 * @description: 自定義飽和策略(拋棄舊任務策略)
 */
class RejectedDiscardOldestPolicy implements RejectedExecutionHandler {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 執(zhí)行任務的標識
     */
    private String taskId;

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public RejectedDiscardOldestPolicy(String taskId) {
        this.taskId = taskId;
    }

    /**
     * @description: 先將阻塞隊列中的當前任務拋棄,再嘗試提交任務。如果此時阻塞隊列使用PriorityBlockingQueue優(yōu)先級隊列,將會導致優(yōu)先級最高的任務被拋棄,因此不建議將該種策略配合優(yōu)先級隊列使用。
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (!executor.isShutdown()) {
            executor.getQueue().poll();
            executor.execute(r);
        }
        logger.error("RejectedDiscardOldestPolicy.rejectedExecution,taskId:{}", taskId);
    }

}


/**
 * @description: 自定義飽和策略(調用者運行)
 */
class RejectedCallerRunsPolicy implements RejectedExecutionHandler {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 執(zhí)行任務的標識
     */
    private String taskId;

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public RejectedCallerRunsPolicy(String taskId) {
        this.taskId = taskId;
    }

    /**
     * @description: 既不拋棄任務也不拋出異常,直接運行任務的run方法,換言之將任務回退給調用者來直接運行。
     * 使用該策略時線程池飽和后將由調用線程池的主線程自己來執(zhí)行任務,
     * 因此在執(zhí)行任務的這段時間里主線程無法再提交新任務,從而使線程池中工作線程有時間將正在處理的任務處理完成。
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (!executor.isShutdown()) {
            r.run();
        }
        logger.warn("RejectedCallerRunsPolicy.rejectedExecution,taskId:{}", taskId);
    }

}

代碼參考博文

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容