AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

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

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

來源: 責編: 時間:2024-01-08 09:13:51 217觀看
導讀1. 問題&分析迭代剛上線,小艾同學又接到了一線業務的投訴,一起看下本次遇到的又是什么問題。1.1. 案例上周接到一個需求,需要對系統中的核心操作增加操作日志,也就是在操作完成后對操作人、操作時間等信息進行詳細記錄。

1. 問題&分析

迭代剛上線,小艾同學又接到了一線業務的投訴,一起看下本次遇到的又是什么問題。OxH28資訊網——每日最新資訊28at.com

1.1. 案例

上周接到一個需求,需要對系統中的核心操作增加操作日志,也就是在操作完成后對操作人、操作時間等信息進行詳細記錄。核心包括:創建訂單、取消訂單、刪除訂單、修改價格等。OxH28資訊網——每日最新資訊28at.com

在需求分析時,小艾做了深度思考:記錄操作日志不能影響正常的業務操作,比如創建訂單,哪怕是操作日志記錄失敗,也不能導致下單失敗。OxH28資訊網——每日最新資訊28at.com

當然,方案1便是,記錄日志的邏輯使用 try-catch 進行處理,哪怕是拋出異常也不能影響原來的主流程。OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

這樣做確實能控制住異常,但由于是在主線程中運行,這樣會導致整個流程的處理時間加長。這時,小艾想起了線程池的異常操作,整體如下:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

這個方案好處多多:OxH28資訊網——每日最新資訊28at.com

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

核心代碼如下:OxH28資訊網——每日最新資訊28at.com

@GetMapping("createOrder")public RestResult<String> createOrder(Integer taskId){    log.info("begin to create Order {}", taskId);    // 創建訂單    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@Slf4jpublic 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() {        // 實際執行業務邏輯,保存到數據庫    }}

在收到業務反饋時,小艾第一時間查看日志,居然沒有找到任何異常信息。難道是業務反饋信息有問題?根據業務提供的訂單號,在數據庫中確實沒有找到操作記錄,好奇怪呀。OxH28資訊網——每日最新資訊28at.com

從日志中提取出 正常 和 異常 信息,分別如下:OxH28資訊網——每日最新資訊28at.com

正常日志:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

可以看出:OxH28資訊網——每日最新資訊28at.com

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

異常日志:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

可以看出少了些信息:OxH28資訊網——每日最新資訊28at.com

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

對比日志可見,==保存操作日志的任務執行失敗,同時系統沒有拋出任何異常?。?!==OxH28資訊網——每日最新資訊28at.com

1.2. 問題分析

核心還是對 線程池的核心 API 不熟悉,當使用 `execute()` 方法提交任務時,異常信息不會直接拋出給調用者。這是因為線程池處理任務的方式是,將這些任務封裝到一個 `Runnable` 中去執行。`Runnable.run()` 方法沒有任何拋出異常的聲明,所以在運行 `Runnable` 時產生的異常只會被內部捕獲,不會拋出。OxH28資訊網——每日最新資訊28at.com

線程池中提供兩者函數:OxH28資訊網——每日最新資訊28at.com

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

2. 解決方案

最大困擾原因是:出問題后沒有任何信息。所以對應的解決方案便是:讓系統能夠打印異常棧暴露異常原因。OxH28資訊網——每日最新資訊28at.com

2.1. 手工拋出異常

最簡單方式便是,在Task代碼中通 try-catch 手工捕獲并打印異常日志。OxH28資訊網——每日最新資訊28at.com

詳細代碼如下:OxH28資訊網——每日最新資訊28at.com

@Slf4jpublic 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);        }    }}

當出現異常數據時,日志如下:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

可以看出,從 SaveOperationLogTask1 類中清楚的打印異常信息。OxH28資訊網——每日最新資訊28at.com

2.2. 封裝 Runnable 統一管理異常

每個 Task 都手工添加 try-catch 邏輯,不僅工作量大也非常容易出現遺漏場景,我們需要一個更好的方案。OxH28資訊網——每日最新資訊28at.com

可以構建一個 Runnable 的封裝類來對異常進行統一處理,詳細代碼如下:OxH28資訊網——每日最新資訊28at.com

@Slf4jpublic 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);        }    }}// 在提交任務時,使用 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);

當出現異常數據時,日志如下:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

可以看出,從 LogBasedTaskWrapper 類中清楚的打印異常信息。OxH28資訊網——每日最新資訊28at.com

2.3. 定制化線程工廠

Wrapper 機制不錯,但需要對 Task 進行封裝操作,還是容易被遺漏,我們還需要更簡單的方式。OxH28資訊網——每日最新資訊28at.com

可以對線程池的線程工廠進行定制,對為捕獲異常進行特殊處理,詳細代碼如下:OxH28資訊網——每日最新資訊28at.com

executorServiceV2 = new ThreadPoolExecutor(4, 4,        0L, TimeUnit.MILLISECONDS,        new LinkedBlockingQueue<Runnable>(20),        new BasicThreadFactory.Builder()                .namingPattern("BlackHole_thread-%d")                // 設置為捕獲異常處理器                .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))。當出現未捕獲異常時,會統一被 UncaughtExceptionHandler 處理。詳細日志如下:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

從日志中看到,從 ExceptionBlackHoleFixController 類中對異常進行處理。OxH28資訊網——每日最新資訊28at.com

這是一勞永逸的方法,也是最鼓勵的方法。OxH28資訊網——每日最新資訊28at.com

2.4. 使用 CompletableFuture

當使用 submit 提交任務時,會返回 Futrue 對象,通過 Future 的 get 方法便可以獲取任務運行的異常信息,但這樣會阻塞主線程導致接口響應時間過長。OxH28資訊網——每日最新資訊28at.com

這種情況下,可以使用更高級的 CompletableFuture,向 CompletableFuture 設置異常處理器后,出現異常時會自動調用處理器,核心代碼如下:OxH28資訊網——每日最新資訊28at.com

// 異步保存操作日志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);

當出現異常數據時,日志如下:OxH28資訊網——每日最新資訊28at.com

圖片imageOxH28資訊網——每日最新資訊28at.com

從日志中看到,從 ExceptionBlackHoleFixController 類中對異常進行處理。OxH28資訊網——每日最新資訊28at.com

3. 示例&源碼

代碼倉庫:https://gitee.com/litao851025/learnFromBugOxH28資訊網——每日最新資訊28at.com

代碼地址:https://gitee.com/litao851025/learnFromBug/tree/master/src/main/java/com/geekhalo/demo/thread/exceptionblackholeOxH28資訊網——每日最新資訊28at.com


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

本文鏈接:http://www.tebozhan.com/showinfo-26-57841-0.html線程池異常黑洞及其防范策略

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

上一篇: 一加 Ace 3 Pop-up 快閃活動來襲,二十城掀起搶購熱潮

下一篇: 如何使用Kotlin開發DSL?

標簽:
  • 熱門焦點
  • K60 Pro官方停產 第三方瞬間漲價

    雖然沒有官方宣布,但Redmi的一些高管也已經透露了,Redmi K60 Pro已經停產且不會補貨,這一切都是為了即將到來的K60 Ultra鋪路,屬于廠家的正常操作。但有意思的是該機在停產之后
  • 直屏旗艦來了 iQOO 12和K70 Pro同臺競技

    旗艦機基本上使用的都是雙曲面屏幕,這就讓很多喜歡直屏的愛好者在苦等一款直屏旗艦,這次,你們等到了。據博主數碼閑聊站帶來的最新爆料稱,Redmi下代旗艦K70 Pro和iQOO 12兩款手
  • 石頭自清潔掃拖機器人G10S評測:多年黑科技集大成之作 懶人終極福音

    科技圈經常能看到一個詞叫“縫合怪”,用來形容那些把好多功能或者外觀結合在一起的產品,通常這樣的詞是貶義詞,但如果真的是產品縫合的好、縫合的實用的話,那它就成了中性詞,今
  • 7月安卓手機性價比榜:努比亞+紅魔兩款新機入榜

    7月登場的新機有努比亞Z50S Pro和紅魔8S Pro,除了三星之外目前唯二的兩款搭載超頻版驍龍8Gen2處理器的產品,而且努比亞和紅魔也一貫有著不錯的性價比,所以在本次的性價比榜單
  • 花7萬退貨退款無門:誰在縱容淘寶珠寶商家造假?

    來源:極點商業作者:楊銘在淘寶購買珠寶玉石后,因為保證金不夠賠付,店鋪關閉,退貨退款難、維權無門的比比皆是。&ldquo;提供相關產品鑒定證書,支持全國復檢,可以30天無理由退換貨。&
  • 年輕人的“職場羞恥感”,無處不在

    作者:馮曉亭 陶 淘 李 欣 張 琳 馬舒葉來源:燃次元&ldquo;人在職場,應該選擇什么樣的著裝?&rdquo;近日,在網絡上,一個與著裝相關的帖子引發關注,在該帖子里,一位在高級寫字樓亞洲金
  • 華為HarmonyOS 4升級計劃公布:首批34款機型今日開啟公測

    8月4日消息,今天下午華為正式發布了HarmonyOS 4系統,在更流暢的前提下,還帶來了不少新功能,UI設計也有變化,會讓手機煥然一新。華為宣布,首批機型將會在
  • OPPO K11搭載長壽版100W超級閃充:26分鐘充滿100%

    據此前官方宣布,OPPO將于7月25日也就是今天下午14:30舉辦新品發布會,屆時全新的OPPO K11將正式與大家見面,將主打旗艦影像,和同檔位競品相比,其最大的賣
  • 蘋果140W USB-C充電器:采用氮化鎵技術

    據10 月 30 日 9to5 Mac 消息報道,當蘋果推出新的 MacBook Pro 2021 時,該公司還推出了新的 140W USB-C 充電器,附贈在 MacBook Pro 16 英寸機型的盒子里,也支
Top