日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

面試必問:線程池是如何執行的?它的拒絕策略有哪些?

來源: 責編: 時間:2023-08-20 23:17:03 549觀看
導讀聊到線程池就一定會聊到線程池的執行流程,也就是當有一個任務進入線程池之后,線程池是如何執行的?我們今天就來聊聊這個話題。線程池是如何執行的?線程池的拒絕策略有哪些?線程池執行流程想要真正的了解線程池的執行流程,就

Xrc28資訊網——每日最新資訊28at.com

聊到線程池就一定會聊到線程池的執行流程,也就是當有一個任務進入線程池之后,線程池是如何執行的?我們今天就來聊聊這個話題。線程池是如何執行的?線程池的拒絕策略有哪些?Xrc28資訊網——每日最新資訊28at.com

線程池執行流程

想要真正的了解線程池的執行流程,就得先從線程池的執行方法 execute() 說起,execute() 實現源碼如下:Xrc28資訊網——每日最新資訊28at.com

public void execute(Runnable command) {    if (command == null)        throw new NullPointerException();    int c = ctl.get();    // 當前工作的線程數小于核心線程數    if (workerCountOf(c) < corePoolSize) {        // 創建新的線程執行此任務        if (addWorker(command, true))            return;        c = ctl.get();    }    // 檢查線程池是否處于運行狀態,如果是則把任務添加到隊列    if (isRunning(c) && workQueue.offer(command)) {        int recheck = ctl.get();        // 再次檢線程池是否處于運行狀態,防止在第一次校驗通過后線程池關閉        // 如果是非運行狀態,則將剛加入隊列的任務移除        if (! isRunning(recheck) && remove(command))            reject(command);        // 如果線程池的線程數為 0 時(當 corePoolSize 設置為 0 時會發生)        else if (workerCountOf(recheck) == 0)            addWorker(null, false); // 新建線程執行任務    }    // 核心線程都在忙且隊列都已爆滿,嘗試新啟動一個線程執行失敗    else if (!addWorker(command, false))         // 執行拒絕策略        reject(command);}

從上述源碼我們可以看出,當任務來了之后,線程池的執行流程是:先判斷當前線程數是否大于核心線程數?如果結果為 false,則新建線程并執行任務;如果結果為 true,則判斷任務隊列是否已滿?如果結果為 false,則把任務添加到任務隊列中等待線程執行,否則則判斷當前線程數量是否超過最大線程數?如果結果為 false,則新建線程執行此任務,否則將執行線程池的拒絕策略,如下圖所示:Xrc28資訊網——每日最新資訊28at.com

Xrc28資訊網——每日最新資訊28at.com

線程池拒絕策略

當任務過多且線程池的任務隊列已滿時,此時就會執行線程池的拒絕策略,線程池的拒絕策略默認有以下 4 種:Xrc28資訊網——每日最新資訊28at.com

  1. AbortPolicy:中止策略,線程池會拋出異常并中止執行此任務。
  2. CallerRunsPolicy:把任務交給添加此任務的(main)線程來執行。
  3. DiscardPolicy:忽略此任務,忽略最新的一個任務。
  4. DiscardOldestPolicy:忽略最早的任務,最先加入隊列的任務。

默認的拒絕策略為 AbortPolicy 中止策略。Xrc28資訊網——每日最新資訊28at.com

DiscardPolicy拒絕策略

接下來我們以 DiscardPolicy 忽略此任務,忽略最新的一個任務為例,演示一下拒絕策略的具體使用,實現代碼如下:Xrc28資訊網——每日最新資訊28at.com

public static void main(String[] args) {    // 任務的具體方法    Runnable runnable = new Runnable() {        @Override        public void run() {            System.out.println("當前任務被執行,執行時間:" + new Date() +                               " 執行線程:" + Thread.currentThread().getName());            try {                // 等待 1s                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    };    // 創建線程,線程的任務隊列的長度為 1    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),                                                           new ThreadPoolExecutor.DiscardPolicy());    // 添加并執行 4 個任務    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);    // 線程池執行完任務,關閉線程池    threadPool.shutdown();}

以上程序的執行結果如下:Xrc28資訊網——每日最新資訊28at.com

Xrc28資訊網——每日最新資訊28at.com

從上述執行結果可以看出,給線程池添加了 4 個任務,而線程池只執行了 2 個任務就結束了,其他兩個任務執行了拒絕策略 DiscardPolicy 被忽略了,這就是拒絕策略的作用。Xrc28資訊網——每日最新資訊28at.com

AbortPolicy拒絕策略

為了和 DiscardPolicy 拒絕策略對比,我們來演示一下 JDK 默認的拒絕策略 AbortPolicy 中止策略,線程池會拋出異常并中止執行此任務,示例代碼如下:Xrc28資訊網——每日最新資訊28at.com

public static void main(String[] args) {    // 任務的具體方法    Runnable runnable = new Runnable() {        @Override        public void run() {            System.out.println("當前任務被執行,執行時間:" + new Date() +                               " 執行線程:" + Thread.currentThread().getName());            try {                // 等待 1s                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    };    // 創建線程,線程的任務隊列的長度為 1    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),                                                           new ThreadPoolExecutor.AbortPolicy()); // 顯式指定拒絕策略,也可以忽略此設置,它為默認拒絕策略    // 添加并執行 4 個任務    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);    // 線程池執行完任務,關閉線程池    threadPool.shutdown();}

以上程序的執行結果如下:Xrc28資訊網——每日最新資訊28at.com

Xrc28資訊網——每日最新資訊28at.com

從結果可以看出,給線程池添加了 4 個任務,線程池正常執行了 2 個任務,其他兩個任務執行了中止策略,并拋出了拒絕執行的異常 RejectedExecutionException。Xrc28資訊網——每日最新資訊28at.com

自定義拒絕策略

當然除了 JDK 提供的四種拒絕策略之外,我們還可以實現通過 new RejectedExecutionHandler,并重寫 rejectedExecution 方法來實現自定義拒絕策略,實現代碼如下:Xrc28資訊網——每日最新資訊28at.com

public static void main(String[] args) {    // 任務的具體方法    Runnable runnable = new Runnable() {        @Override        public void run() {            System.out.println("當前任務被執行,執行時間:" + new Date() +                               " 執行線程:" + Thread.currentThread().getName());            try {                // 等待 1s                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    };    // 創建線程,線程的任務隊列的長度為 1    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),                                                           new RejectedExecutionHandler() {                                                               @Override                                                               public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {                                                                   // 執行自定義拒絕策略的相關操作                                                                   System.out.println("我是自定義拒絕策略~");                                                               }                                                           });    // 添加并執行 4 個任務    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);    threadPool.execute(runnable);}

以上程序的執行結果如下:Xrc28資訊網——每日最新資訊28at.com

Xrc28資訊網——每日最新資訊28at.com

小結

線程池的執行流程有 3 個重要的判斷點(判斷順序依次往后):判斷當前線程數和核心線程數、判斷當前任務隊列是否已滿、判斷當前線程數是否已達到最大線程數。如果經過以上 3 個判斷,得到的結果都會 true,則會執行線程池的拒絕策略。JDK 提供了 4 種拒絕策略,我們還可以通過 new RejectedExecutionHandler 并重寫 rejectedExecution 方法來實現自定義拒絕策略。Xrc28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-6174-0.html面試必問:線程池是如何執行的?它的拒絕策略有哪些?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 六種在 React 中獲取數據的方法

下一篇: 揭穿DevOps的5個謠言!

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 泸溪县| 墨脱县| 平湖市| 西乌珠穆沁旗| 卢湾区| 兖州市| 四川省| 瑞昌市| 卓尼县| 天水市| 宣恩县| 东光县| 古丈县| 扬州市| 永德县| 靖宇县| 陆丰市| 嘉义市| 通州市| 江达县| 阿拉善左旗| 周宁县| 鄢陵县| 峨眉山市| 舒兰市| 南通市| 宁晋县| 秦皇岛市| 同江市| 白城市| 湄潭县| 勃利县| 舟曲县| 嘉兴市| 阿克陶县| 哈密市| 庆安县| 宜都市| 巴楚县| 五河县| 民权县|