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

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

故障現場 | 這個死鎖出奇的詭異

來源: 責編: 時間:2024-02-01 12:52:21 301觀看
導讀1. 問題&分析線程池用多了總會出現些詭異問題,特別是當任務間的關系比較復雜時,經常會出現讓你想象不到問題,比如這次出現的這個問題。1.1. 案例突然間,系統出現大量報警,具體信息如下:圖片從拋出的異常可知,提交量較大導致

1. 問題&分析

線程池用多了總會出現些詭異問題,特別是當任務間的關系比較復雜時,經常會出現讓你想象不到問題,比如這次出現的這個問題。5FZ28資訊網——每日最新資訊28at.com

1.1. 案例

突然間,系統出現大量報警,具體信息如下:5FZ28資訊網——每日最新資訊28at.com

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

從拋出的異常可知,提交量較大導致線程池資源被耗盡,從而觸發了線程池的拒絕策略,直接拋出了 RejectedExecutionException。5FZ28資訊網——每日最新資訊28at.com

開始的時候,小艾認為等高峰流量過去后,系統便能恢復正常。可出乎意料的是,系統一直沒有恢復,那么流量已經將至個位數,請求也是 100% 失敗,同時該節點的大量后臺任務都出現異常。沒有辦法,為了快速止損,不得已對異常節點進行重啟,系統隨之恢復正常,日志輸入如下:5FZ28資訊網——每日最新資訊28at.com

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

其他的后臺任務也恢復正常。5FZ28資訊網——每日最新資訊28at.com

驚魂初定的小艾找到出問題的代碼如下:5FZ28資訊網——每日最新資訊28at.com

@GetMapping("syncSubmit")public RestResult<String> syncSubmit(String taskName){    this.executeService.submit(new ParentTask());    return RestResult.success("提交成功");}class ParentTask implements Callable<Boolean>{    @Override    public Boolean call() throws Exception {        Future<A> aFuture = executeService.submit(new FetchAChildTask());        doSomeThing(500);        Future<B> bFuture = executeService.submit(new FetchBChildTask());        doSomeThing(500);        C c = buildC(aFuture.get(), bFuture.get());        Future<Boolean> cFuture = executeService.submit(new SaveCChildTask(c));        return cFuture.get();    }}

代碼的邏輯非常簡單,核心流程如下圖所示:5FZ28資訊網——每日最新資訊28at.com

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

核心流程為:5FZ28資訊網——每日最新資訊28at.com

  1. 提交異步任務,并行獲取 A 和 B
  2. 線程同步處理一下耗時操作
  3. 獲取 A 和 B 結果后,構建新對象 C
  4. 將 C 保存到數據庫

邏輯非常簡單,唯一的復雜點在于:==多處任務提交使用了統一線程池。==5FZ28資訊網——每日最新資訊28at.com

【背景】考慮到線程池是系統中最寶貴的資源,公司“大牛”封裝了一個全局的 GlobalExecuteService 服務,并制定規范要求所有異步任務統一使用 GlobalExecuteService 來完成。如果需要構建自己的線程池,需要向他提交審批,只有在審批后才能創建新的線程池。5FZ28資訊網——每日最新資訊28at.com

1.2. 問題分析

線程池處于什么狀態?為什么所有異步任務都無法提交?5FZ28資訊網——每日最新資訊28at.com

這是一個比較燒腦的問題,單盤邏輯沒有什么頭緒,沒有辦法只能將現場 dump 下來進行分析。5FZ28資訊網——每日最新資訊28at.com

第一個問題:線程池線程都處于什么狀態,線程棧信息如下:5FZ28資訊網——每日最新資訊28at.com

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

從日志中可知:5FZ28資訊網——每日最新資訊28at.com

  1. 線程池中的線程全部處于 WAITING,也就是等待狀態;
  2. 展開 Thread-1 棧信息,發現線程再調用 future.get 操作時出現阻塞
  3. 實際等待對象為 FutrueTask#10

接下來,需要進一步確認 FutureTask#10 具體處于什么狀態,從內存堆中找到 FutureTask#10 對象,詳細信息如下:5FZ28資訊網——每日最新資訊28at.com

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

從日志中可以看出:5FZ28資訊網——每日最新資訊28at.com

  1. FutureTask#10 是 LinkedBlockingQueue 的 Node 節點持有,也就是 FutureTask#10 處于等待隊列中
  2. 該阻塞隊列屬于 GlobalExecuteService 所有

排查到這里,真相浮出水面:GlobalExecuteService 中的線程,正在等待 GlobalExecuteService 阻塞隊列的任務完成。5FZ28資訊網——每日最新資訊28at.com

具體如下圖所示:5FZ28資訊網——每日最新資訊28at.com

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

線程池中的所有工作線程都在等待阻塞隊列的任務完成,由于沒有可用的工作線程,阻塞隊列中的任務永遠都不會被執行。5FZ28資訊網——每日最新資訊28at.com

這就是典型的死鎖!!!5FZ28資訊網——每日最新資訊28at.com

2. 解決方案

費了老大勁終于定位問題,解決思路也就變的明了:不要向自己運行的線程池提交任務。5FZ28資訊網——每日最新資訊28at.com

圖解如下:5FZ28資訊網——每日最新資訊28at.com

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

線程池不會向自己提交任務,而是將任務提交到其他線程池。5FZ28資訊網——每日最新資訊28at.com

2.1. 手工拆分線程池

問題修復變的簡單,我們需要:5FZ28資訊網——每日最新資訊28at.com

  1. 先建一個子線程池服務
  2. 父線程池向子線程池提交任務

具體代碼如下:5FZ28資訊網——每日最新資訊28at.com

@Autowiredprivate GlobalExecuteService executeService;// 創建新的線程池服務@Autowiredprivate SubExecuteService subExecuteService;@GetMapping("syncSubmit")public RestResult<String> syncSubmit(String taskName){    this.executeService.submit(new ParentTask());    return RestResult.success("提交成功");}class ParentTask implements Callable<Boolean>{    @Override    public Boolean call() throws Exception {        log.info("Begin to Run Parent Task");        // 向新的線程池服務提交任務        Future<A> aFuture = subExecuteService.submit(new FetchAChildTask());        doSomeThing(500);        // 向新的線程池服務提交任務        Future<B> bFuture = subExecuteService.submit(new FetchBChildTask());        doSomeThing(500);        C c = buildC(aFuture.get(), bFuture.get());        // 向新的線程池服務提交任務        Future<Boolean> cFuture = subExecuteService.submit(new SaveCChildTask(c));        Boolean result = cFuture.get();        log.info("End to Run Parent Task");        return result;    }}

2.2. 多級任務管理

手工拆分線程池確實能解決這個場景的問題,但由于 GlobalExecuteService 服務已經使用很長時間,任務間的關系錯綜復雜,很難一次性排查并修復所有問題,同時隨著邏輯的變化未來仍舊會出現類似的問題。5FZ28資訊網——每日最新資訊28at.com

那最佳方案是什么?5FZ28資訊網——每日最新資訊28at.com

讓 GlobalExecuteService 具備多級管理能力。核心代碼如下:5FZ28資訊網——每日最新資訊28at.com

@Servicepublic class GlobalExecuteServiceV2 {    // 記錄當前線程運行級別,默認 0,表示當前線程非該類管理的線程池線程    private static final ThreadLocal<Integer> LEVEL_HOLDER = ThreadLocal.withInitial(()->0);    // 一級線程池    private ExecutorService executorServiceLeve1;    // 二級線程池    private ExecutorService executorServiceLeve2;    // 默認線程池    private ExecutorService defExecutorService;    @PostConstruct    public void init() {       // 省略線程池初始化邏輯    }    public <T> Future<T> submit(Callable<T> callable){        // 獲取當前線程的運行級別        Integer level = LEVEL_HOLDER.get();        // 根據當前運行級別,計算子任務所使用的線程池        ExecutorService executorService = getNextExecutorServiceByLevel(level);        // 為子任務分配運行級別        CallableWrapper<T> callableWrapper = new CallableWrapper<>(level + 1, callable);        // 提交任務        return executorService.submit(callableWrapper);    }    private ExecutorService getNextExecutorServiceByLevel(Integer level) {        if (level == 0){            return executorServiceLeve1;        }        if (level == 1){            return executorServiceLeve2;        }        return defExecutorService;    }    class CallableWrapper<T> implements Callable<T>{        private final Integer level;        private final Callable<T> callable;        CallableWrapper(Integer level, Callable<T> callable) {            this.level = level;            this.callable = callable;        }        @Override        public T call() throws Exception {            try {                // 為線程池綁定運行級別                LEVEL_HOLDER.set(level);                return callable.call();            }finally {                // 清理線程池運行級別                LEVEL_HOLDER.remove();            }        }    }}

核心設計如下:5FZ28資訊網——每日最新資訊28at.com

  1. 使用 ThreadLocal<Integer> LEVEL_HOLDER 記錄當前線程運行的級別,默認為 0 表示任務未在線程池中運行
  2. 提交任務時,通過當前運行級別計算下一級別的線程池
  • 當前級別為0,返回 Level1 線程池
  • 當前級別為1,返回 Level2 線程池
  • 其他基本,返回 默認 線程池
  1. 通過 CallableWrapper 自動將任務運行的 Level 綁定到當前線程上下文
  2. 任務執行前,使用 LEVEL_HOLDER.set(level) 完成運行 level 的設置
  3. 任務執行后,使用 LEVEL_HOLDER.remove() 完成運行 level 的清理

為了演示方便,僅定義了 3 級線程池,通常情況下足夠業務使用,但需要注意:5FZ28資訊網——每日最新資訊28at.com

  • 超過三級提交,仍舊有可以出現死鎖的情況,可以通過日志方式及時暴露問題
  • 如不放心,可以升級為 “無限極” 設計,及使用 List<ExecutorService> 對線程池進行統一管理,并根據 Level 完成線程池的動態創建

3. 示例&源碼

代碼倉庫:5FZ28資訊網——每日最新資訊28at.com

https://gitee.com/litao851025/learnFromBug5FZ28資訊網——每日最新資訊28at.com

代碼地址:5FZ28資訊網——每日最新資訊28at.com

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

本文鏈接:http://m.www897cc.com/showinfo-26-70483-0.html故障現場 | 這個死鎖出奇的詭異

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

上一篇: CSS 和 SVG 實現彩色圖片陰影

下一篇: 我們一起聊聊React列表渲染與Key

標簽:
  • 熱門焦點
  • Mate60手機殼曝光 致敬自己的經典設計

    8月3日消息,今天下午博主數碼閑聊站帶來了華為Mate60的第三方手機殼圖,可以讓我們在真機發布之前看看這款華為全新旗艦的大致輪廓。從曝光的圖片看,Mate 60背后攝像頭面積依然
  • 三言兩語說透設計模式的藝術-簡單工廠模式

    一、寫在前面工廠模式是最常見的一種創建型設計模式,通常說的工廠模式指的是工廠方法模式,是使用頻率最高的工廠模式。簡單工廠模式又稱為靜態工廠方法模式,不屬于GoF 23種設計
  • 一文看懂為蘋果Vision Pro開發應用程序

    譯者 | 布加迪審校 | 重樓蘋果的Vision Pro是一款混合現實(MR)頭戴設備。Vision Pro結合了虛擬現實(VR)和增強現實(AR)的沉浸感。其高分辨率顯示屏、先進的傳感器和強大的處理能力
  • Java NIO內存映射文件:提高文件讀寫效率的優秀實踐!

    Java的NIO庫提供了內存映射文件的支持,它可以將文件映射到內存中,從而可以更快地讀取和寫入文件數據。本文將對Java內存映射文件進行詳細的介紹和演示。內存映射文件概述內存
  • 如何使用JavaScript創建一只圖像放大鏡?

    譯者 | 布加迪審校 | 重樓如果您曾經瀏覽過購物網站,可能遇到過圖像放大功能。它可以讓您放大圖像的特定區域,以便瀏覽。結合這個小小的重要功能可以大大改善您網站的用戶體驗
  • 中國家電海外掘金正當時|出海專題

    作者|吳南南編輯|胡展嘉運營|陳佳慧出品|零態LT(ID:LingTai_LT)2023年,出海市場戰況空前,中國創業者在海外紛紛摩拳擦掌,以期能夠把中國的商業模式、創業理念、戰略打法輸出海外,他們依
  • 一條抖音4億人圍觀 ! 這家MCN比無憂傳媒還野

    作者:Hiu 來源:互聯網品牌官01 擦邊少女空降熱搜,幕后推手曝光被網友譽為&ldquo;純欲天花板&rdquo;的女網紅井川里予,近期因為一組哥特風照片登上熱搜,引發了一場互聯網世界關于
  • 小米汽車電池信息疑似曝光:容量101kWh,支持800V高壓快充

    7月14日消息,今日一名博主在社交媒體發布了一張疑似小米汽車電池信息的照片,顯示該電池包正是寧德時代麒麟電池,容量為101kWh,電壓為726.7V,可以預測小
  • 聯想小新Pad Pro 12.6將要推出,搭載高通驍龍 870 處理器

    聯想小新Pad Pro 12.6將于秋季新品會上推出,官方按照慣例直接在發布會前給出了機型的所有參數。聯想小新 Pad Pro 12.6 將搭載高通驍龍 870 處理器,重量為 5
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产精品白丝av嫩草影院 | 国产免费成人| 欧美三级中文字幕在线观看| 国产精品成人一区二区网站软件 | 在线免费不卡视频| 亚洲美女黄网| 亚洲欧美日韩在线高清直播| 久久久久国产一区二区三区| 欧美成人一区在线| 国产精品video| 国产一区二区三区日韩| 亚洲成人原创 | 久久视频在线视频| 欧美精品午夜| 国产精品久久久久久久久久免费看| 国产日产欧产精品推荐色 | 欧美亚洲综合久久| 免费观看在线综合| 欧美深夜福利| 黄色成人av在线| 夜夜嗨av一区二区三区中文字幕| 欧美一区2区视频在线观看 | 久久午夜视频| 欧美三日本三级少妇三2023 | 欧美日韩国产一区二区三区地区| 国产精品一区二区你懂的| ●精品国产综合乱码久久久久| 亚洲午夜视频在线| 老司机一区二区| 国产精品视频网| 亚洲国产精品黑人久久久| 午夜精品久久久久久久99热浪潮| 欧美电影免费观看高清完整版| 国产女人精品视频| 99视频+国产日韩欧美| 久久日韩粉嫩一区二区三区| 欧美日韩和欧美的一区二区| 极品中文字幕一区| 亚洲欧美bt| 欧美大片91| 国内偷自视频区视频综合| 亚洲一区二区三区国产| 欧美大片在线看| 国产一区在线看| 亚洲一区精品视频| 欧美欧美全黄| 亚洲二区在线观看| 久久爱www久久做| 国产精品国产一区二区 | 性xx色xx综合久久久xx| 欧美日韩一卡| 亚洲精品你懂的| 老司机精品视频一区二区三区| 国产欧美视频一区二区三区| 亚洲天堂免费观看| 欧美精品激情在线| 在线日韩欧美视频| 久久久97精品| 国产亚洲女人久久久久毛片| 亚洲一区免费视频| 欧美日韩久久久久久| 亚洲激情不卡| 另类国产ts人妖高潮视频| 国产一区二区三区久久| 亚洲摸下面视频| 欧美性猛交视频| 一区二区免费看| 欧美日韩的一区二区| 亚洲茄子视频| 欧美国产日韩一区二区在线观看 | 欧美国产精品一区| 亚洲国产精品第一区二区三区| 久久亚洲一区二区三区四区| 国产日韩欧美视频| 香蕉久久夜色精品国产| 国产精品入口福利| 亚洲一区二区三区久久| 国产精品s色| 亚洲午夜电影网| 国产精品嫩草影院av蜜臀| 亚洲线精品一区二区三区八戒| 欧美日韩一区二区在线视频| 一个人看的www久久| 欧美日韩日本国产亚洲在线 | 小嫩嫩精品导航| 国产性做久久久久久| 欧美亚洲一级| 国产亚洲一区精品| 久久久久这里只有精品| 精品不卡在线| 蜜臀91精品一区二区三区| 亚洲国产成人精品视频| 欧美国产极速在线| 日韩视频在线一区二区| 欧美日韩一区三区四区| 亚洲视频综合在线| 国产精品久久久久久亚洲调教| 亚洲免费在线观看视频| 国产日韩专区| 久久综合久久综合久久| 亚洲国产99精品国自产| 欧美精品九九99久久| 一本色道久久综合狠狠躁篇怎么玩| 欧美三区美女| 欧美伊人影院| 亚洲第一毛片| 欧美日韩国产高清| 亚洲欧美在线高清| 韩国女主播一区二区三区| 免费亚洲婷婷| 一区二区三区精品在线| 国产美女精品免费电影| 久久人人97超碰国产公开结果| 最新日韩精品| 国产精品久久久久久久久久尿 | 最新日韩精品| 国产精品盗摄久久久| 欧美在线亚洲| 亚洲国内自拍| 国产精品国产三级国产普通话三级 | 国产欧美在线视频| 卡一卡二国产精品| 日韩一区二区精品| 国产精品夜色7777狼人| 久久一区免费| 一二三区精品福利视频| 国产日本欧美一区二区三区| 麻豆freexxxx性91精品| 在线亚洲+欧美+日本专区| 国产欧美日韩综合一区在线观看 | 欧美午夜精彩| 久久久久九九九九| 一本到高清视频免费精品| 国产亚洲欧美日韩在线一区| 欧美国产欧美亚州国产日韩mv天天看完整| 中文亚洲视频在线| 国产综合欧美| 欧美日韩在线播放| 久久久亚洲一区| 亚洲午夜精品国产| 在线观看日韩av电影| 欧美三级在线播放| 免费成人性网站| 午夜精品亚洲一区二区三区嫩草| 亚洲福利一区| 国产精品爽黄69| 欧美国产日韩一区| 久久成人免费网| 一区二区三区免费观看| 激情欧美一区| 国产精品激情电影| 猛男gaygay欧美视频| 亚洲欧美日韩中文视频| 最新国产成人在线观看| 国内精品久久久| 国产精品成av人在线视午夜片| 久久视频精品在线| 亚洲女人天堂av| 亚洲美女91| 在线成人亚洲| 国产欧美日韩精品a在线观看| 欧美人交a欧美精品| 久久人人97超碰国产公开结果| 亚洲欧美日韩国产另类专区| 亚洲美女电影在线| 亚洲第一成人在线| 国产亚洲欧洲997久久综合| 欧美色网在线| 欧美激情第3页| 久久一区激情| 久久精品91久久久久久再现| 这里是久久伊人| 亚洲日产国产精品| 激情久久久久久久| 国产欧美日韩免费看aⅴ视频| 欧美日韩精品久久| 欧美激情va永久在线播放| 久热精品视频在线| 久久久久久电影| 欧美在线首页| 午夜在线精品| 午夜精品久久| 亚洲欧美日韩在线播放| 亚洲天堂偷拍| 一区二区三区日韩欧美| 亚洲伦理在线观看| 亚洲国内精品在线| 在线观看成人网| 伊人久久综合97精品| 韩国av一区二区三区四区| 国产日韩视频一区二区三区| 国产精品视频精品视频| 国产精品扒开腿做爽爽爽视频| 欧美三级韩国三级日本三斤| 欧美伦理91i| 欧美精品偷拍| 欧美日韩dvd在线观看| 欧美黑人一区二区三区| 欧美高清一区| 欧美激情亚洲激情| 欧美激情视频一区二区三区免费| 欧美成人在线免费观看| 欧美成人久久| 欧美劲爆第一页|