自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么阿里巴巴Java開發(fā)手冊禁止使用Executors創(chuàng)建線程池?

開發(fā) 前端
當(dāng)你的應(yīng)用在高峰期突然宕機,日志中出現(xiàn)大量OOM異常時,你是否想過罪魁禍首可能是那幾行看似無害的Executors代碼?

在Java并發(fā)編程中,線程池是提高系統(tǒng)性能的關(guān)鍵組件,而Executors工廠方法提供了創(chuàng)建線程池的便捷途徑。許多開發(fā)者習(xí)慣性地使用Executors.newFixedThreadPool()或Executors.newCachedThreadPool()來快速實現(xiàn)并發(fā)任務(wù)處理,殊不知這種看似便利的方式卻暗藏巨大風(fēng)險。

當(dāng)你的應(yīng)用在高峰期突然宕機,日志中出現(xiàn)大量OOM異常時,你是否想過罪魁禍首可能是那幾行看似無害的Executors代碼?這正是為什么《阿里巴巴Java開發(fā)手冊》將"禁止使用Executors創(chuàng)建線程池"列為強制性規(guī)范。

在這里插入圖片描述

一、為什么禁止使用Executors工廠方法

1.資源耗盡風(fēng)險

newFixedThreadPool和newSingleThreadExecutor,內(nèi)部使用無界的LinkedBlockingQueue,允許請求隊列無限增長,可能導(dǎo)致OOM(內(nèi)存溢出)

newCachedThreadPool和newScheduledThreadPool,允許創(chuàng)建的線程數(shù)量為Integer.MAX_VALUE,可能會創(chuàng)建大量線程,導(dǎo)致系統(tǒng)資源耗盡

2.無法精細控制

工廠方法使用了預(yù)設(shè)的參數(shù),無法根據(jù)實際業(yè)務(wù)場景進行精細調(diào)整,隱藏了線程池的實際運行機制,開發(fā)人員難以意識到潛在風(fēng)險。

二、案例1:電商系統(tǒng)中的訂單處理服務(wù)OOM問題

在電商系統(tǒng)的秒殺活動中,訂單處理服務(wù)使用Executors.newFixedThreadPool(10)創(chuàng)建線程池,當(dāng)遇到大量請求時,任務(wù)隊列無限增長導(dǎo)致內(nèi)存溢出。

newFixedThreadPool內(nèi)部使用LinkedBlockingQueue沒有設(shè)置容量上限,請求堆積時內(nèi)存會持續(xù)增長。

// 問題代碼
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 大量提交任務(wù)
for (Order order : orders) {
    executorService.submit(() -> processOrder(order));
}

使用ThreadPoolExecutor手動創(chuàng)建線程池,并設(shè)置合理的隊列大小和拒絕策略。

// 優(yōu)化后的代碼
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5,                       // 核心線程數(shù)
    10,                      // 最大線程數(shù)
    60L, TimeUnit.SECONDS,   // 線程空閑超時時間
    new LinkedBlockingQueue<>(1000), // 有界隊列,容量為1000
    new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("order-process-thread-" + t.getId());
            return t;
        }
    },
    new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略:由調(diào)用線程執(zhí)行
);

// 提交任務(wù)
for (Order order : orders) {
    executor.submit(() -> processOrder(order));
}

隊列有明確的容量上限防止內(nèi)存溢出,線程數(shù)有明確上限,使用CallerRunsPolicy在系統(tǒng)超負荷時能夠自動降速,自定義線程名稱便于問題排查。

三、案例2:定時任務(wù)系統(tǒng)線程爆炸

企業(yè)內(nèi)部的定時任務(wù)系統(tǒng)使用Executors.newCachedThreadPool()處理各類定時任務(wù),隨著業(yè)務(wù)增長,某天系統(tǒng)突然無響應(yīng)。

// 問題代碼
ExecutorService executor = Executors.newCachedThreadPool();
// 定時任務(wù)系統(tǒng)中添加各種任務(wù)
for (Task task : tasks) {
    executor.submit(() -> executeTask(task));
}

newCachedThreadPool允許創(chuàng)建的最大線程數(shù)是Integer.MAX_VALUE,當(dāng)系統(tǒng)負載較高時,會創(chuàng)建過多線程,導(dǎo)致線程上下文切換開銷巨大,最終系統(tǒng)崩潰。

手動創(chuàng)建線程池,限制最大線程數(shù),并增加監(jiān)控。

// 優(yōu)化后的代碼
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    10,                      // 核心線程數(shù)
    50,                      // 最大線程數(shù)(明確上限)
    3, TimeUnit.MINUTES,     // 非核心線程存活時間
    new ArrayBlockingQueue<>(2000), // 有界隊列
    new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("scheduled-task-" + t.getId());
            t.setDaemon(true); // 設(shè)置為守護線程
            return t;
        }
    },
    new ThreadPoolExecutor.AbortPolicy() // 任務(wù)拒絕時拋出異常,便于及時發(fā)現(xiàn)問題
);

// 添加監(jiān)控
executor.setRejectedExecutionHandler((r, e) -> {
    log.error("任務(wù)隊列已滿,任務(wù)被拒絕執(zhí)行");
    // 觸發(fā)告警通知
    alertService.sendAlert("線程池隊列已滿,請檢查系統(tǒng)負載!");
    throw new RejectedExecutionException("線程池任務(wù)隊列已滿");
});

// 提交任務(wù)
for (Task task : tasks) {
    executor.submit(() -> executeTask(task));
}

明確限制最大線程數(shù)防止線程爆炸,避免過多的線程上下文切換,異常情況下能夠快速發(fā)現(xiàn)并告警,隊列和線程數(shù)都有明確上限。

在這里插入圖片描述

四、手動創(chuàng)建線程池的好處

1.資源可控性更強

明確指定線程數(shù)上限和任務(wù)隊列容量,避免資源耗盡。防止OOM(內(nèi)存溢出)和線程爆炸問題,系統(tǒng)資源使用更加可預(yù)測和穩(wěn)定。

2.業(yè)務(wù)適配性更好

根據(jù)業(yè)務(wù)特點精確調(diào)整參數(shù),為IO密集型任務(wù)設(shè)置較高的線程數(shù),為CPU密集型任務(wù)設(shè)置相對較少的線程數(shù),可以針對不同業(yè)務(wù)場景設(shè)計不同參數(shù)配置的線程池。

3.異常處理更加優(yōu)雅

自定義拒絕策略,系統(tǒng)超負荷時可以優(yōu)雅降級,可以選擇合適的策略:調(diào)用者運行、丟棄任務(wù)、丟棄最老任務(wù)或拋出異常,甚至可以實現(xiàn)自定義的復(fù)雜拒絕處理邏輯,如將任務(wù)存入數(shù)據(jù)庫等。

4.監(jiān)控能力更強

添加自定義監(jiān)控和告警邏輯,可以實時監(jiān)控線程池狀態(tài),如活躍線程數(shù)、隊列深度等,在異常情況下及時觸發(fā)告警,避免系統(tǒng)崩潰。

5.問題排查更便捷

通過自定義ThreadFactory給線程池中的線程合理命名,便于在日志和線程轉(zhuǎn)儲中快速定位問題,可以添加額外的線程元數(shù)據(jù),如來源業(yè)務(wù)、優(yōu)先級等。

五、總結(jié)

《阿里巴巴Java開發(fā)手冊》禁止使用Executors創(chuàng)建線程池的規(guī)定并非過度謹慎,而是基于大量生產(chǎn)實踐經(jīng)驗總結(jié)出的寶貴教訓(xùn)。通過手動創(chuàng)建ThreadPoolExecutor,我們能夠明確控制線程數(shù)量上限和任務(wù)隊列容量,有效防止資源耗盡導(dǎo)致的系統(tǒng)崩潰。

在高并發(fā)場景下,線程池配置不當(dāng)引發(fā)的問題往往具有突發(fā)性和災(zāi)難性,可能在系統(tǒng)長期穩(wěn)定運行后的某個峰值時刻突然爆發(fā)。正確的做法是遵循"自定義線程池參數(shù)、限制資源上限、設(shè)置拒絕策略、加強監(jiān)控告警"的原則,根據(jù)業(yè)務(wù)特性精細調(diào)整線程池配置。

責(zé)任編輯:姜華 來源: 哪吒編程
相關(guān)推薦

2019-11-13 14:38:34

Executors阿里線程池

2020-09-14 09:47:56

Java開發(fā)類型

2024-01-03 08:15:35

Executors線程池線程

2024-02-28 07:37:53

JavaExecutors工具

2020-09-08 16:25:18

Apache BeancopyJava

2020-07-30 12:16:33

阿里巴巴Apache對象

2017-05-02 21:14:20

阿里巴巴Java開發(fā)

2020-09-22 11:40:53

BigDecimalequalsJava

2019-09-04 11:02:54

繼承層次組合

2019-09-02 15:20:28

Java開發(fā)繼承

2018-10-16 15:34:17

阿里巴巴Apache Flin大數(shù)據(jù)

2022-09-05 10:06:21

MySQL外循環(huán)內(nèi)循環(huán)

2021-09-17 06:28:20

JOIN阿里Java

2021-08-04 17:20:30

阿里巴巴AsyncJava

2022-08-30 16:38:30

阿里巴巴JavaLog4j

2013-08-22 09:26:38

去IOE王堅

2021-10-11 09:32:40

包裝類型屬性

2016-09-21 20:28:55

阿里巴巴IOE

2019-03-04 09:22:52

阿里巴巴foreach Java

2019-06-26 07:54:53

ArrayListsubList源碼
點贊
收藏

51CTO技術(shù)棧公眾號