精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

線程池異常黑洞及其防范策略

開發(fā) 前端
當使用 submit 提交任務(wù)時,會返回 Futrue 對象,通過 Future 的 get 方法便可以獲取任務(wù)運行的異常信息,但這樣會阻塞主線程導(dǎo)致接口響應(yīng)時間過長。

1. 問題&分析

迭代剛上線,小艾同學(xué)又接到了一線業(yè)務(wù)的投訴,一起看下本次遇到的又是什么問題。

1.1. 案例

上周接到一個需求,需要對系統(tǒng)中的核心操作增加操作日志,也就是在操作完成后對操作人、操作時間等信息進行詳細記錄。核心包括:創(chuàng)建訂單、取消訂單、刪除訂單、修改價格等。

在需求分析時,小艾做了深度思考:記錄操作日志不能影響正常的業(yè)務(wù)操作,比如創(chuàng)建訂單,哪怕是操作日志記錄失敗,也不能導(dǎo)致下單失敗。

當然,方案1便是,記錄日志的邏輯使用 try-catch 進行處理,哪怕是拋出異常也不能影響原來的主流程。

圖片圖片

這樣做確實能控制住異常,但由于是在主線程中運行,這樣會導(dǎo)致整個流程的處理時間加長。這時,小艾想起了線程池的異常操作,整體如下:

圖片圖片

這個方案好處多多:

  1. 可以非常好對異常進行隔離,任務(wù)執(zhí)行發(fā)生異常也不會影響主流程
  2. 操作日志在線程池中異步處理,不會占用主線程的時間,整體操作時間變化不大

核心代碼如下:

@GetMapping("createOrder")
public RestResult<String> createOrder(Integer taskId){
    log.info("begin to create Order {}", taskId);
    // 創(chuàng)建訂單
    doCreateOrder(taskId);
    log.info("end to create Order {}", taskId);

    // 異步保存操作日志
    log.info("Begin to Submit Task {}", taskId);
    this.executorService.execute(new SaveOperationLogTask(taskId));
    log.info("Success to Submit Task {}", taskId);
    return RestResult.success("提交成功");
}

// 保存操作日志 Task
@Slf4j
public class SaveOperationLogTask implements Runnable {
    // 省略部分代碼
    @Override
    public void run() {
        log.info("Begin to save operation");
        // 保存日志
        saveLog();
        log.info("Success to Run task {}", this.taskId);
    }

    private void saveLog() {
        // 實際執(zhí)行業(yè)務(wù)邏輯,保存到數(shù)據(jù)庫
    }
}

在收到業(yè)務(wù)反饋時,小艾第一時間查看日志,居然沒有找到任何異常信息。難道是業(yè)務(wù)反饋信息有問題?根據(jù)業(yè)務(wù)提供的訂單號,在數(shù)據(jù)庫中確實沒有找到操作記錄,好奇怪呀。

從日志中提取出 正常 和 異常 信息,分別如下:

正常日志:

圖片圖片

可以看出:

  1. 在主線程中完成創(chuàng)建訂單和提交任務(wù)操作
  2. 在線程池線程中完成操作日志保存操作
  3. 在數(shù)據(jù)庫中能看到詳細的操作信息

異常日志:

圖片圖片

可以看出少了些信息:

  1. 主線程操作沒有變化,完成了創(chuàng)建訂單和提交任務(wù)操作
  2. 線程池線程只打印了開始執(zhí)行的日志,未見到執(zhí)行成功日志
  3. 數(shù)據(jù)中也沒有操作信息

對比日志可見,==保存操作日志的任務(wù)執(zhí)行失敗,同時系統(tǒng)沒有拋出任何異常!!!==

1.2. 問題分析

核心還是對 線程池的核心 API 不熟悉,當使用 `execute()` 方法提交任務(wù)時,異常信息不會直接拋出給調(diào)用者。這是因為線程池處理任務(wù)的方式是,將這些任務(wù)封裝到一個 `Runnable` 中去執(zhí)行。`Runnable.run()` 方法沒有任何拋出異常的聲明,所以在運行 `Runnable` 時產(chǎn)生的異常只會被內(nèi)部捕獲,不會拋出。

線程池中提供兩者函數(shù):

  1. `execute()` 方法用于提交不需要返回值的任務(wù),所以無法判斷任務(wù)是否被線程池成功執(zhí)行。
  2. `submit()` 方法用于提交需要返回值的任務(wù)。線程池會返回一個 future 類型的對象,通過這個 future 對象可以判斷任務(wù)是否執(zhí)行成功。

2. 解決方案

最大困擾原因是:出問題后沒有任何信息。所以對應(yīng)的解決方案便是:讓系統(tǒng)能夠打印異常棧暴露異常原因。

2.1. 手工拋出異常

最簡單方式便是,在Task代碼中通 try-catch 手工捕獲并打印異常日志。

詳細代碼如下:

@Slf4j
public class SaveOperationLogTask1 implements Runnable {
    // 省略非核心代碼
    @Override
    public void run() {
        try {
            int result = RandomUtils.nextInt() / this.taskId;
            log.info("Success to Run task {}", this.taskId);
        }catch (Exception e) {
            log.error("failed to run task {}", taskId, e);
        }
    }
}

當出現(xiàn)異常數(shù)據(jù)時,日志如下:

圖片圖片

可以看出,從 SaveOperationLogTask1 類中清楚的打印異常信息。

2.2. 封裝 Runnable 統(tǒng)一管理異常

每個 Task 都手工添加 try-catch 邏輯,不僅工作量大也非常容易出現(xiàn)遺漏場景,我們需要一個更好的方案。

可以構(gòu)建一個 Runnable 的封裝類來對異常進行統(tǒng)一處理,詳細代碼如下:

@Slf4j
public class LogBasedTaskWrapper implements Runnable {
    private final Runnable runnable;

    public LogBasedTaskWrapper(Runnable runnable) {
        this.runnable = runnable;
    }

    @Override
    public void run() {
        try {
            this.runnable.run();
        }catch (Exception e) {
            log.error("Filed to run task {}", runnable, e);
        }
    }
}

// 在提交任務(wù)時,使用 LogBasedTaskWrapper 對 Task 進行封裝即可
log.info("Begin to Submit Task {}", taskId);
Runnable task = new SaveOperationLogTask(taskId);
this.executorService.execute(new LogBasedTaskWrapper(task));
log.info("Success to Submit Task {}", taskId);

當出現(xiàn)異常數(shù)據(jù)時,日志如下:

圖片圖片

可以看出,從 LogBasedTaskWrapper 類中清楚的打印異常信息。

2.3. 定制化線程工廠

Wrapper 機制不錯,但需要對 Task 進行封裝操作,還是容易被遺漏,我們還需要更簡單的方式。

可以對線程池的線程工廠進行定制,對為捕獲異常進行特殊處理,詳細代碼如下:

executorServiceV2 = new ThreadPoolExecutor(4, 4,
        0L, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>(20),
        new BasicThreadFactory.Builder()
                .namingPattern("BlackHole_thread-%d")
                // 設(shè)置為捕獲異常處理器
                .uncaughtExceptionHandler((t, e) -> log.error("Failed to run task", e))
                .build(),
        new ThreadPoolExecutor.AbortPolicy());

// 然后使用 executorServiceV2 即可
// 異步保存操作日志
log.info("Begin to Submit Task {}", taskId);
this.executorServiceV2.execute(new SaveOperationLogTask(taskId));
log.info("Success to Submit Task {}", taskId);

核心代碼就一句:.uncaughtExceptionHandler((t, e) -> log.error("Failed to run task", e))。當出現(xiàn)未捕獲異常時,會統(tǒng)一被 UncaughtExceptionHandler 處理。詳細日志如下:

圖片圖片

從日志中看到,從 ExceptionBlackHoleFixController 類中對異常進行處理。

這是一勞永逸的方法,也是最鼓勵的方法。

2.4. 使用 CompletableFuture

當使用 submit 提交任務(wù)時,會返回 Futrue 對象,通過 Future 的 get 方法便可以獲取任務(wù)運行的異常信息,但這樣會阻塞主線程導(dǎo)致接口響應(yīng)時間過長。

這種情況下,可以使用更高級的 CompletableFuture,向 CompletableFuture 設(shè)置異常處理器后,出現(xiàn)異常時會自動調(diào)用處理器,核心代碼如下:

// 異步保存操作日志
log.info("Begin to Submit Task {}", taskId);
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(new SaveOperationLogTask(taskId), this.executorService);
completableFuture.exceptionally(e -> {
        log.error("Failed to Submit Task", e);
        return null;
    }
);
log.info("Success to Submit Task {}", taskId);

當出現(xiàn)異常數(shù)據(jù)時,日志如下:

圖片圖片

image

從日志中看到,從 ExceptionBlackHoleFixController 類中對異常進行處理。

3. 示例&源碼

代碼倉庫:https://gitee.com/litao851025/learnFromBug

代碼地址:https://gitee.com/litao851025/learnFromBug/tree/master/src/main/java/com/geekhalo/demo/thread/exceptionblackhole


責(zé)任編輯:武曉燕 來源: geekhalo
相關(guān)推薦

2020-11-25 11:33:47

Java線程技術(shù)

2025-02-24 00:00:10

.NET線程池模型

2025-04-28 00:55:00

2025-05-09 10:14:19

2024-10-09 15:58:02

2020-07-08 12:05:55

Java線程池策略

2025-07-17 07:26:47

2020-02-18 14:25:51

Java線程池拒絕策略

2023-12-29 09:38:00

Java線程池

2024-09-13 09:06:22

2012-02-13 17:26:35

2013-05-09 09:13:41

2022-11-24 09:00:00

2011-09-05 10:40:45

2023-05-19 08:01:24

Key消費場景

2022-03-14 07:32:06

線程池拒絕策略自定義

2010-01-30 11:23:59

2016-09-01 21:19:55

2014-06-06 09:30:07

2011-03-14 10:10:01

點贊
收藏

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

亚洲精品成人区在线观看| 老司机午夜网站| www.国产色| 日韩有码av| 日本韩国精品在线| 国产99视频精品免费视频36| 国产在线视频二区| 少妇一区二区三区| 在线视频观看一区| 亚洲视频在线二区| 91高潮大合集爽到抽搐| 你懂的国产精品永久在线| 亚洲福利视频二区| av网站在线不卡| 色yeye免费人成网站在线观看| 国产一区二区三区免费在线观看| 久久久久成人网| 亚洲永久精品ww.7491进入| 亚洲第一影院| 亚洲视频小说图片| 国产亚洲福利社区| 国产精品无码粉嫩小泬| 伊人久久大香线蕉精品组织观看| 亚洲国产免费av| 美女黄色片视频| 污污网站在线看| 91在线高清观看| 96pao国产成视频永久免费| 日韩福利小视频| 九九热爱视频精品视频| 欧美一区二区三区四区久久| 欧美日韩性生活片| 成人免费视屏| 国产校园另类小说区| 成人xxxxx色| 亚洲影视一区二区| 中日韩男男gay无套| 久久成人亚洲精品| 中文字幕成人动漫| 成人性生交大片免费看96| 欧美色精品在线视频| 久久久久久久午夜| 欧美1—12sexvideos| 亚洲国产高清在线观看视频| 精品久久精品久久| 精品国产av 无码一区二区三区 | 欧美一区二区视频17c| 国产高清视频免费观看| 日韩在线一区二区| 日韩av成人在线| 日韩三级av在线| 欧美精品导航| 久久久国产视频| 后入内射无码人妻一区| 美女毛片一区二区三区四区最新中文字幕亚洲 | 国产精品高清乱码在线观看| 亚洲线精品一区二区三区| 日韩精品一区二区三区电影| 你懂得网站在线| 久久综合av免费| 极品校花啪啪激情久久| 黄色美女一级片| 国产成人亚洲综合a∨婷婷图片 | 五月天婷婷激情| 亚洲国产精品91| 亚洲欧美日韩精品| 高清中文字幕mv的电影| 久久精品免视看国产成人| 色天天综合久久久久综合片| 天堂资源在线亚洲资源| 亚洲毛片在线播放| 成人听书哪个软件好| 国产传媒一区二区| 黄色一级大片在线免费看国产一 | 亚洲精品女av网站| 中国精品一区二区| 美国av一区二区| 国产噜噜噜噜久久久久久久久| 在线视频免费观看一区| 久久久天天操| 国产精品视频区| 91麻豆一区二区| 精品影院一区二区久久久| 亚洲一区二区三| 亚洲成人第一区| jlzzjlzz国产精品久久| 久久国产精品免费一区| 欧美午夜黄色| 国产精品欧美综合在线| 日韩 欧美 自拍| 午夜激情在线| 亚洲一区二区av在线| 国产1区2区3区中文字幕| 91破解版在线观看| 欧美日韩国产色| 日日噜噜夜夜狠狠| 国产精品久久久久77777丨| 欧美狂野另类xxxxoooo| 美女露出粉嫩尿囗让男人桶| 亚洲成人一品| 精品国产一区二区三区久久| 久久伊人成人网| 亚洲欧美视频一区二区三区| 国产美女91呻吟求| 人妻无码中文字幕| 国产精品三级av| 国产一级不卡视频| av有码在线观看| 色激情天天射综合网| 三区视频在线观看| 天美av一区二区三区久久| 尤物yw午夜国产精品视频明星| 日本精品在线免费观看| 亚洲精品裸体| 成人黄色大片在线免费观看| 五月天婷婷在线观看| 欧美国产综合一区二区| 国产在线视频综合| free欧美| 精品粉嫩超白一线天av| 萌白酱视频在线| 亚洲综合国产激情另类一区| 亚洲在线免费看| 毛片网站在线观看| 亚洲一二三级电影| 九九热免费在线观看| 日韩美女国产精品| 欧美久久久精品| 久久久久精彩视频| 99久久精品久久久久久清纯| av磁力番号网| jizz亚洲女人高潮大叫| 日韩精品视频在线观看免费| 91视频综合网| 青青草伊人久久| 国产免费一区二区| 超碰在线caoporen| 欧美日韩国产首页| 熟女俱乐部一区二区视频在线| 一区二区蜜桃| 国产精品一香蕉国产线看观看| 天堂成人在线| 亚洲国产日韩一级| 2018国产精品| 永久91嫩草亚洲精品人人| 国产精品女主播| 免费的黄色av| 亚洲综合偷拍欧美一区色| 一区二区免费av| 全国精品免费看| 久久久亚洲成人| 国产黄色一区二区| 亚洲精品中文在线| 韩国一区二区在线播放| 天天综合亚洲| 国产欧美精品日韩| 一级日本在线| 欧美日韩一区二区三区四区| 三区四区在线观看| 免费精品视频在线| 亚洲欧美日韩另类精品一区二区三区 | 狠狠色狠色综合曰曰| 亚洲精品国产成人av在线| 国产精品99免费看| 国产成人精品日本亚洲11| 国产网红在线观看| 亚洲电影第1页| 国产亚洲欧美精品久久久www| 国产剧情av麻豆香蕉精品| 免费观看黄色大片| 欧美成人精品午夜一区二区| 欧美日韩国产成人在线| 午夜精品久久久久久久爽| 亚洲一区二区在线视频| 深夜做爰性大片蜜桃| 欧美在线日韩| 福利视频久久| 国产美女高潮在线| 在线日韩日本国产亚洲| 亚洲一级片免费看| 国产精品大尺度| 亚洲五月激情网| 在线高清一区| 韩国成人一区| 欧美日韩在线精品一区二区三区激情综合 | 久操手机在线视频| 999久久久精品一区二区| 4438全国亚洲精品在线观看视频| 国产综合在线观看| 在线播放一区二区三区| 久久久精品91| 久久午夜羞羞影院免费观看| 午夜精品在线免费观看| 天天揉久久久久亚洲精品| 91成人免费在线观看| av中文字幕在线观看第一页 | 日本久久电影网| 麻豆网址在线观看| 国产宾馆实践打屁股91| 日本精品一区在线观看| 久久久影院免费| 国产精品二区三区四区| 播放一区二区| 欧美激情videoshd| 国产youjizz在线| 欧美大片一区二区| 国产又粗又猛又黄视频| 国产精品国产自产拍高清av| 精品少妇人妻av一区二区三区| 久久久天天操| 久久精品国产精品亚洲精品色| 久久久伦理片| 91九色国产在线| 午夜不卡影院| 久久精品福利视频| 日韩av资源| 日韩欧美黄色影院| 精品一区二区无码| 欧美日韩久久久久| 国产网址在线观看| 一区二区三区欧美视频| 中文乱码字幕高清一区二区| 日本一区二区三区dvd视频在线| 亚洲av成人片色在线观看高潮| 国产成人免费视频一区| 性欧美在线视频| 精品亚洲aⅴ乱码一区二区三区| 国产欧美高清在线| 香蕉成人久久| 国产亚洲欧美在线视频| 99国产精品久久久久久久| 分分操这里只有精品| 国产综合精品| 久久综合久久网| 亚洲青色在线| 国产a级片网站| 亚洲黄色高清| 国产精品va无码一区二区| 亚洲国产专区校园欧美| 日韩中文字幕在线免费| 亚洲激情综合| 国产免费黄视频| 欧美专区在线| 免费看a级黄色片| 日韩二区三区在线观看| 欧美日韩亚洲自拍| 毛片av一区二区| www.国产福利| 国产精品1区二区.| 中文字幕99页| 97精品国产97久久久久久久久久久久| 在线观看国产免费视频| 91免费在线看| 久久久久久成人网| 亚洲欧美aⅴ...| 久久国产精品波多野结衣| 亚洲一区二区三区爽爽爽爽爽| 国产在线拍揄自揄拍无码视频| 五月激情六月综合| 成人午夜精品视频| 欧美精品黑人性xxxx| 精品人妻少妇嫩草av无码专区| 日韩欧美美女一区二区三区| 神马久久久久久久久久| 亚洲人成网在线播放| 欧美私人网站| 欧美精品www在线观看| 日韩av影片| 国产精品久久久久免费a∨| 精品中文视频| 精品伦理一区二区三区| 成人看的视频| av在线免费观看国产| 久久精品伊人| 911av视频| 91丝袜美腿高跟国产极品老师| 精品无码人妻一区二区免费蜜桃| 中文字幕亚洲区| 日本午夜小视频| 91久久精品午夜一区二区| 一区二区三区午夜| 精品国产精品一区二区夜夜嗨| 久久久资源网| 欧美精品免费在线观看| 中文字幕 在线观看| 91在线视频成人| 亚洲a级精品| 永久免费看av| 日本女人一区二区三区| av在线天堂网| 欧美激情资源网| www.天天色| 91精品国产91久久久久久一区二区| 人妻一区二区三区| 最近更新的2019中文字幕 | 欧美在线影院在线视频| 91精品视频一区二区| 精品欧美一区二区久久久伦| 91免费精品| 国产成人久久777777| 丁香六月久久综合狠狠色| 欧美午夜激情影院| 欧美视频精品一区| 高清国产mv在线观看| www亚洲欧美| 日韩高清在线| 精品综合在线| 黑丝一区二区三区| 嫩草视频免费在线观看| 久久精品人人做人人综合| 日韩欧美一级视频| 欧美白人最猛性xxxxx69交| 欧美成年黄网站色视频| 国产精品草莓在线免费观看| 久久精品色播| 97久久国产亚洲精品超碰热| 久久精品国产**网站演员| 日本黄色特级片| 午夜精品久久久久久| 午夜精品久久久久久久99老熟妇| 日韩一中文字幕| 成人在线黄色| 日韩精品资源| 久久精品官网| 女~淫辱の触手3d动漫| 五月天国产精品| 丰满少妇高潮在线观看| 欧美成人精品在线观看| 国产精品亚洲一区二区在线观看| 亚洲欧美国产不卡| 六月丁香婷婷色狠狠久久| 日韩免费成人av| 欧美偷拍一区二区| www.国产精品.com| 国产精品第2页| 清纯唯美日韩| 婷婷激情5月天| 亚洲人成小说网站色在线| 国产又粗又猛又爽| 久久国产色av| 91蜜桃臀久久一区二区| 黄色激情在线视频| 成人av手机在线观看| 日韩欧美不卡视频| 亚洲欧美国产一区二区三区| 亚洲女同av| 亚洲精品一区二| 久久精品999| 五月天婷婷色综合| 精品剧情在线观看| av日韩中文| 日本一区视频在线播放| 男女激情视频一区| www.99re7| 精品va天堂亚洲国产| 日韩影院在线| 欧美性色黄大片人与善| 麻豆一区二区99久久久久| 四虎884aa成人精品| 日韩你懂的在线播放| av第一福利在线导航| 欧美三日本三级少妇三99| 美女网站一区二区| 欧美久久久久久久久久久久| 亚洲第一区第一页| 亚洲伦乱视频| 中国女人做爰视频| 91影院在线免费观看| 99成人精品视频| 欧美日韩国产成人| 美女少妇全过程你懂的久久| 亚洲久久中文字幕| 亚洲激情图片qvod| 视频一区二区三区国产| 国产精品久久久久久久久久三级| 亚洲精品成人无限看| 岛国精品资源网站| 欧美日韩视频在线第一区| 国产在线更新| 久久99精品久久久水蜜桃| 久久精品国产99国产| 在线看成人av| 在线观看日韩av| 91成人福利| www.日本xxxx| 亚洲一区影音先锋| av电影在线播放高清免费观看| av免费精品一区二区三区| 天堂一区二区在线| 国产性一乱一性一伧一色| 一本色道久久88亚洲综合88| 亚洲一区电影| 午夜免费福利视频在线观看| 性做久久久久久久久| 日本精品一区二区三区在线播放| 久久一区二区三区av| 国产福利91精品一区| 在线视频欧美亚洲| 国产91精品网站| 亚洲青涩在线|