最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程池拒絕策略場景分析

 更新時(shí)間:2026年04月01日 08:55:06   作者:敖正煬  
不同的業(yè)務(wù)場景對任務(wù)丟失的容忍度、響應(yīng)延遲的要求、系統(tǒng)保護(hù)的需求各不相同,本文就來介紹一下Java線程池拒絕策略場景分析,感興趣的可以了解一下

不同的業(yè)務(wù)場景對任務(wù)丟失的容忍度、響應(yīng)延遲的要求、系統(tǒng)保護(hù)的需求各不相同。下面通過 6 個(gè)典型場景,分析如何選擇合適的拒絕策略,并給出代碼示例和注意事項(xiàng)。

場景1:電商訂單支付(核心交易鏈路)

業(yè)務(wù)特點(diǎn)

  • 每一筆支付請求都必須處理,不能丟失。
  • 支付操作涉及數(shù)據(jù)庫更新、第三方網(wǎng)關(guān)調(diào)用、消息發(fā)送等。
  • 要求高一致性,失敗需要明確感知并觸發(fā)重試或補(bǔ)償。

壓力情況:大促時(shí)瞬間流量激增,線程池可能飽和。

選擇策略AbortPolicy + 上層統(tǒng)一捕獲異常,進(jìn)行異步重試或放入死信隊(duì)列。

理由

  • 支付任務(wù)絕對不能靜默丟棄(DiscardPolicy 不可用)。
  • 不能讓調(diào)用者線程執(zhí)行支付任務(wù)(CallerRunsPolicy 會(huì)阻塞 Tomcat 線程,導(dǎo)致整個(gè)服務(wù)響應(yīng)變慢)。
  • 拋出異常是最明確的失敗信號,由調(diào)用方(通常是 Controller 或 Service)捕獲后,可以將任務(wù)轉(zhuǎn)儲(chǔ)到消息隊(duì)列或數(shù)據(jù)庫,稍后重試。

代碼示例

// 線程池配置
@Bean("paymentExecutor")
public Executor paymentExecutor() {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        20, 50, 60L, TimeUnit.SECONDS,
        new ArrayBlockingQueue<>(200),
        new NamedThreadFactory("payment"),
        new ThreadPoolExecutor.AbortPolicy()  // 顯式拋出異常
    );
    return executor;
}

// 業(yè)務(wù)調(diào)用處
@Service
public class PaymentService {
    @Autowired
    private ThreadPoolExecutor paymentExecutor;
    
    public void processPayment(PaymentRequest request) {
        try {
            paymentExecutor.execute(() -> doPayment(request));
        } catch (RejectedExecutionException e) {
            // 線程池飽和,將任務(wù)寫入重試隊(duì)列(如 RocketMQ、Redis 等)
            saveToRetryQueue(request);
            log.warn("Payment task rejected, saved to retry queue. requestId={}", request.getId());
            // 可選:向調(diào)用方返回“系統(tǒng)繁忙,稍后重試”的提示
        }
    }
}

監(jiān)控指標(biāo):拒絕次數(shù)必須為 0,一旦出現(xiàn)立即告警并擴(kuò)容。

場景2:秒殺扣庫存(瞬時(shí)高并發(fā),允許快速失?。?/h2>

業(yè)務(wù)特點(diǎn)

  • 請求量瞬間爆炸,但真正能成功秒殺到的用戶只有一小部分。
  • 要求極低的響應(yīng)延遲,不能排隊(duì)等待。
  • 超出處理能力的請求應(yīng)該被快速拒絕,返回“已售罄”或“系統(tǒng)繁忙”。

壓力情況:QPS 從幾百瞬間飆升到幾十萬。

選擇策略AbortPolicyDiscardPolicy + 前端友好提示。

理由

  • 使用 SynchronousQueue + 有限最大線程數(shù)(如 200),任何超出并發(fā)能力的請求立即觸發(fā)拒絕。
  • AbortPolicy 拋異常,或者用 DiscardPolicy 靜默丟棄,但都需要在業(yè)務(wù)層捕獲并返回統(tǒng)一的失敗響應(yīng)。
  • 不能使用 CallerRunsPolicy,因?yàn)檎{(diào)用者(Tomcat 工作線程)執(zhí)行秒殺任務(wù)會(huì)嚴(yán)重拖垮整個(gè) Web 容器。

代碼示例

// 秒殺專用線程池
int maxConcurrency = 200; // 根據(jù)壓測得出系統(tǒng)能承受的最大并發(fā)扣庫存操作
ExecutorService seckillExecutor = new ThreadPoolExecutor(
    0, maxConcurrency, 30L, TimeUnit.SECONDS,
    new SynchronousQueue<>(),
    new NamedThreadFactory("seckill"),
    new ThreadPoolExecutor.AbortPolicy()
);
// 秒殺接口
@PostMapping("/seckill")
public Result seckill(Long goodsId, Long userId) {
    try {
        seckillExecutor.execute(() -> {
            // 扣庫存、創(chuàng)建訂單等核心操作
            inventoryService.decr(goodsId);
            orderService.create(userId, goodsId);
        });
        return Result.success("搶購中,請稍后查看訂單");
    } catch (RejectedExecutionException e) {
        // 線程池滿,直接返回失敗
        return Result.error("很遺憾,您沒搶到,下次加油");
    }
}

優(yōu)化點(diǎn):可以在拒絕策略中直接記錄指標(biāo),但無需重試,因?yàn)槊霘⑹【褪亲罱K結(jié)果。

場景3:異步發(fā)送短信/郵件(非關(guān)鍵通知,允許少量丟失)

業(yè)務(wù)特點(diǎn)

  • 用戶注冊、下單后發(fā)送確認(rèn)短信/郵件。
  • 即使少量消息發(fā)送失敗,也不影響核心業(yè)務(wù)(用戶可以通過其他渠道重試)。
  • 不希望因消息發(fā)送阻塞主流程。

壓力情況:業(yè)務(wù)高峰時(shí)消息量較大,但系統(tǒng)可以接受一定程度的丟棄。

選擇策略DiscardOldestPolicyDiscardPolicy + 日志記錄。

理由

  • 消息堆積過久反而不如丟棄舊消息,保證新消息能及時(shí)發(fā)出(DiscardOldestPolicy)。
  • 如果消息完全可丟棄(如運(yùn)營推廣短信),直接用 DiscardPolicy。
  • 不能使用 CallerRunsPolicy,因?yàn)橹骶€程(如訂單完成后的異步通知)不應(yīng)被阻塞。

代碼示例

// 通知線程池
ThreadPoolExecutor notifyExecutor = new ThreadPoolExecutor(
    5, 20, 60L, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(500),
    new NamedThreadFactory("notify"),
    new ThreadPoolExecutor.DiscardOldestPolicy()
);
// 發(fā)送短信
public void sendSms(String phone, String content) {
    notifyExecutor.execute(() -> {
        try {
            smsClient.send(phone, content);
        } catch (Exception e) {
            log.error("Send sms failed, phone={}", phone, e);
            // 可選:記錄失敗到數(shù)據(jù)庫,由定時(shí)任務(wù)補(bǔ)償
        }
    });
}

監(jiān)控:可以統(tǒng)計(jì)丟棄數(shù)量,如果丟棄率過高(如 >1%),考慮擴(kuò)容或優(yōu)化短信通道。

場景4:日志/審計(jì)記錄(海量低價(jià)值,可丟棄)

業(yè)務(wù)特點(diǎn)

  • 每條請求都需要記錄訪問日志、用戶行為日志。
  • 數(shù)據(jù)量極大(每秒數(shù)萬條),對實(shí)時(shí)性要求低。
  • 偶爾丟失幾條日志對業(yè)務(wù)無影響。

壓力情況:持續(xù)高吞吐,磁盤或網(wǎng)絡(luò)可能成為瓶頸。

選擇策略DiscardPolicy(靜默丟棄)。

理由

  • 日志系統(tǒng)不應(yīng)該拖垮主業(yè)務(wù)。如果線程池滿了,說明下游(如日志服務(wù)器、ES)已經(jīng)處理不過來,再排隊(duì)只會(huì)加劇問題。
  • 直接丟棄是最簡單有效的自我保護(hù)。
  • 也可以自定義策略,將丟棄的日志采樣記錄(用于分析丟失率)。

代碼示例

ThreadPoolExecutor logExecutor = new ThreadPoolExecutor(
    2, 10, 10L, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(1000),
    new NamedThreadFactory("access-log"),
    new ThreadPoolExecutor.DiscardPolicy()
);
// 記錄訪問日志
public void logAccess(HttpServletRequest request) {
    logExecutor.execute(() -> {
        // 構(gòu)建日志對象,發(fā)送到 Kafka 或?qū)懭氡镜匚募?
        accessLogService.save(parseLog(request));
    });
}

進(jìn)階:可以結(jié)合采樣,在丟棄時(shí)隨機(jī)記錄 1% 的丟棄事件用于監(jiān)控。

場景5:批量數(shù)據(jù)導(dǎo)入(任務(wù)重,不允許丟失,可接受延遲)

業(yè)務(wù)特點(diǎn)

  • 從文件、數(shù)據(jù)庫批量導(dǎo)入數(shù)據(jù),每個(gè)任務(wù)執(zhí)行時(shí)間較長(秒級到分鐘級)。
  • 任務(wù)數(shù)量固定,不允許丟失。
  • 可以接受導(dǎo)入速度變慢,但不能失敗。

壓力情況:任務(wù)提交可能短時(shí)間集中,但總?cè)蝿?wù)量可控。

選擇策略CallerRunsPolicy。

理由

  • 當(dāng)線程池飽和時(shí),由調(diào)用者線程(例如主線程或定時(shí)任務(wù)線程)直接執(zhí)行導(dǎo)入任務(wù),這樣不會(huì)丟失任務(wù),同時(shí)會(huì)自然降低新任務(wù)的提交速度。
  • 因?yàn)閷?dǎo)入任務(wù)本身是重量級操作,調(diào)用者執(zhí)行雖然會(huì)阻塞,但總比丟棄好。
  • 配合有界隊(duì)列,防止內(nèi)存溢出。

代碼示例

ThreadPoolExecutor importExecutor = new ThreadPoolExecutor(
    4, 8, 5L, TimeUnit.MINUTES,
    new ArrayBlockingQueue<>(10),  // 小隊(duì)列,讓拒絕策略盡快生效
    new NamedThreadFactory("data-import"),
    new ThreadPoolExecutor.CallerRunsPolicy()
);
// 批量提交導(dǎo)入任務(wù)
public void importLargeFiles(List<File> files) {
    for (File file : files) {
        importExecutor.execute(() -> importOneFile(file));
    }
    importExecutor.shutdown();
    importExecutor.awaitTermination(1, TimeUnit.HOURS);
}

注意CallerRunsPolicy 可能會(huì)導(dǎo)致調(diào)用者線程長時(shí)間阻塞,如果調(diào)用者是定時(shí)任務(wù)線程,可能影響其他定時(shí)任務(wù)??梢詫⒄{(diào)用者線程池也設(shè)置得足夠健壯。

場景6:與消息隊(duì)列結(jié)合(最終一致性,高可靠性)

業(yè)務(wù)特點(diǎn)

  • 任務(wù)必須處理,但不能阻塞當(dāng)前線程。
  • 希望削峰填谷,利用消息隊(duì)列的持久化能力。

選擇策略:自定義拒絕策略,將任務(wù)轉(zhuǎn)發(fā)到 RocketMQ、Kafka 等。

理由

  • 線程池只處理實(shí)時(shí)部分,當(dāng)線程池飽和時(shí),將任務(wù)寫入消息隊(duì)列,由消費(fèi)者異步處理。
  • 這樣既保護(hù)了系統(tǒng),又保證了任務(wù)不丟失。

代碼示例

public class MQBackedRejectedHandler implements RejectedExecutionHandler {
    private final RocketMQTemplate mqTemplate;
    private final String topic;
    public MQBackedRejectedHandler(RocketMQTemplate mqTemplate, String topic) {
        this.mqTemplate = mqTemplate;
        this.topic = topic;
    }
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (executor.isShutdown()) {
            return;
        }
        // 將任務(wù)序列化后發(fā)送到 MQ
        if (r instanceof SerializableTask) {
            mqTemplate.syncSend(topic, ((SerializableTask) r).getPayload());
        } else {
            // 兜底:記錄到數(shù)據(jù)庫
            saveToDatabase(r);
        }
    }
}
// 線程池配置
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    10, 50, 60L, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(100),
    new NamedThreadFactory("worker"),
    new MQBackedRejectedHandler(mqTemplate, "rejected-task-topic")
);

注意:發(fā)送 MQ 本身也可能失敗,需要做好重試和監(jiān)控。

場景總結(jié)表

業(yè)務(wù)場景推薦拒絕策略理由風(fēng)險(xiǎn)提示
支付/下單(核心交易)AbortPolicy + 上層重試必須明確失敗,不能靜默丟棄調(diào)用方需處理異常
秒殺/搶購(快速失?。?/td>AbortPolicy / DiscardPolicy追求低延遲,超出直接拒絕丟棄率可能較高,前端需友好提示
異步通知(短信/郵件)DiscardOldestPolicy保證新消息優(yōu)先,可少量丟失舊消息可能丟失
日志/審計(jì)DiscardPolicy海量數(shù)據(jù),可丟失監(jiān)控丟棄率,避免過高的丟失
批量導(dǎo)入(不允許丟)CallerRunsPolicy由調(diào)用者執(zhí)行,不丟失調(diào)用者可能阻塞
高可靠異步任務(wù)自定義(轉(zhuǎn) MQ/DB)削峰填谷,保證最終執(zhí)行增加系統(tǒng)復(fù)雜度

最佳實(shí)踐建議

  1. 默認(rèn)不要使用 AbortPolicy 而毫無處理:至少要在業(yè)務(wù)代碼中捕獲 RejectedExecutionException,記錄日志或觸發(fā)降級。
  2. 非核心業(yè)務(wù)優(yōu)先使用 DiscardPolicy 并記錄丟棄次數(shù):用于容量規(guī)劃。
  3. 所有拒絕策略都應(yīng)該有監(jiān)控:通過 Micrometer、Prometheus 暴露 rejected.count 指標(biāo)。
  4. CallerRunsPolicy 要謹(jǐn)慎評估調(diào)用者線程:如果調(diào)用者是 Web 請求線程,可能導(dǎo)致請求超時(shí)堆積。
  5. 自定義拒絕策略時(shí)不要執(zhí)行過于耗時(shí)的操作(如寫數(shù)據(jù)庫、發(fā) MQ),否則會(huì)加劇線程池的阻塞。

通過結(jié)合具體業(yè)務(wù)場景選擇合適的拒絕策略,可以平衡系統(tǒng)穩(wěn)定性、任務(wù)可靠性響應(yīng)延遲三者之間的關(guān)系,構(gòu)建高可用的并發(fā)系統(tǒng)。

到此這篇關(guān)于Java線程池拒絕策略場景分析的文章就介紹到這了,更多相關(guān)Java線程池拒絕策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java讀取PHP接口數(shù)據(jù)的實(shí)現(xiàn)方法

    java讀取PHP接口數(shù)據(jù)的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava讀取PHP接口數(shù)據(jù)的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • 系統(tǒng)運(yùn)維問題排查-java內(nèi)存過高分析及說明

    系統(tǒng)運(yùn)維問題排查-java內(nèi)存過高分析及說明

    本文總結(jié)了監(jiān)控Java進(jìn)程內(nèi)存與線程狀態(tài)的常用命令及參數(shù),包括top排序、jmap查看內(nèi)存分布、jstat分析GC數(shù)據(jù)、jstack解析線程狀態(tài)等,強(qiáng)調(diào)需使用與進(jìn)程一致的用戶執(zhí)行,并解析了線程狀態(tài)和內(nèi)存區(qū)域的含義
    2025-07-07
  • jar包運(yùn)行一段時(shí)間后莫名其妙掛掉線上問題及處理方案

    jar包運(yùn)行一段時(shí)間后莫名其妙掛掉線上問題及處理方案

    這篇文章主要介紹了jar包運(yùn)行一段時(shí)間后莫名其妙掛掉線上問題及處理方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • JAVA破壞單例模式的方式以及避免方法

    JAVA破壞單例模式的方式以及避免方法

    這篇文章主要介紹了JAVA破壞單例模式的方式以及避免方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • java對象初始化代碼詳解

    java對象初始化代碼詳解

    這篇文章主要介紹了java對象初始化代碼詳解,涉及實(shí)例變量的初始化,類變量的初始化等相關(guān)介紹幾代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java常見延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié)

    Java常見延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié)

    Java延遲隊(duì)列(DelayQueue)是Java并發(fā)包中的一個(gè)類,它實(shí)現(xiàn)了BlockingQueue接口,且其中的元素必須實(shí)現(xiàn)Delayed接口,延遲隊(duì)列中的元素按照延遲時(shí)間的長短進(jìn)行排序,本文給大家介紹了Java常見延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié),需要的朋友可以參考下
    2024-03-03
  • Java實(shí)現(xiàn)網(wǎng)絡(luò)文件下載以及下載到指定目錄

    Java實(shí)現(xiàn)網(wǎng)絡(luò)文件下載以及下載到指定目錄

    在Spring框架中,StreamUtils和FileCopyUtils兩個(gè)工具類提供了方便的文件下載功能,它們都屬于org.springframework.util包,可以通過簡單的方法調(diào)用實(shí)現(xiàn)文件流的復(fù)制和下載,這些工具類支持多種參數(shù)傳遞,涵蓋了文件下載的多種場景
    2024-09-09
  • WebSocket獲取httpSession空指針異常的解決辦法

    WebSocket獲取httpSession空指針異常的解決辦法

    這篇文章主要介紹了在使用WebSocket實(shí)現(xiàn)p2p或一對多聊天功能時(shí),如何獲取HttpSession來獲取用戶信息,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-01-01
  • 堆排序算法的講解及Java版實(shí)現(xiàn)

    堆排序算法的講解及Java版實(shí)現(xiàn)

    這篇文章主要介紹了堆排序算法的講解及Java版實(shí)現(xiàn),堆排序基于堆這種數(shù)據(jù)結(jié)構(gòu),在本文中對堆的概念也有補(bǔ)充介紹,需要的朋友可以參考下
    2016-05-05
  • spring?cloud?使用oauth2?問題匯總

    spring?cloud?使用oauth2?問題匯總

    這篇文章主要介紹了spring?cloud?使用oauth2?問題匯總,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09

最新評論

望奎县| 乌海市| 平遥县| 博白县| 南部县| 寻甸| 定远县| 巴林左旗| 福泉市| 平安县| 汽车| 龙门县| 惠东县| 海伦市| 扬州市| 林芝县| 金沙县| 宜昌市| 昌邑市| 阳东县| 孝感市| 玛沁县| 壶关县| 清涧县| 郯城县| 喀什市| 盐亭县| 景德镇市| 武宣县| 固始县| 平陆县| 永济市| 古田县| 托里县| 华安县| 永仁县| 广昌县| 渭南市| 浙江省| 鄱阳县| 尉氏县|