<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          線程池執(zhí)行的用戶任務(wù)拋出異常會怎樣?

          共 3056字,需瀏覽 7分鐘

           ·

          2022-11-22 10:48

          點擊關(guān)注公眾號,Java干貨及時送達??

          來源:blog.csdn.net/qq_26824159/article/details/126767372

          ThreadPoolExecutor.execute

          源碼分析

          看源碼可以知道,ThreadPoolExecutor中的任務(wù)都是在runWorker中執(zhí)行的

          圖片

          通過源碼可以看到

          • 1149行執(zhí)行用戶任務(wù)
          • 1150~1155處理捕獲任務(wù)異常,并拋出
          • 拋出異常后會退出,從任務(wù)隊列中拉取任務(wù)的循環(huán)
          • 然后執(zhí)行1167行,worker線程退出的邏輯

          看一下線程退出的邏輯

          圖片
          • 如果是異常退出,參數(shù)completedAbruptly為true
          • 如果狀態(tài)值比STOP小,即線程池沒有停止,會重新創(chuàng)建一個worker線程
          總結(jié)

          ThreadPoolExecutor.execute 如果用戶任務(wù)拋出了異常,在線程池運行的狀態(tài)下,會重新創(chuàng)建一個worker線程。

          這里就可能存在一個風(fēng)險,即如果用戶任務(wù)大量的拋出異常,可能會導(dǎo)出線程資源頻繁的銷毀、創(chuàng)建。

          因此,需要用戶任務(wù)應(yīng)當主動對異常進行處理,而不是消極的拋給線程池。

          ThreadPoolExecutor.submit

          源碼分析

          通過 ThreadPoolExecutor.submit 提交的用戶任務(wù),會包裝成一個FutureTask,返回一個Future對象。因此異常處理的邏輯和ThreadPoolExecutor.execute有些差別

          看一個FutureTask.run方法

          圖片

          從源碼可以看到,F(xiàn)utureTask執(zhí)行用戶任務(wù),如果異常,不會對外拋出,僅是記錄

          但是在調(diào)用Future.get時,會拋出異常,但此時的線程不是線程池的線程了,而是用戶線程,因此對線程池是友好的。

          總結(jié)

          ThreadPoolExecutor.submit 提交的用戶任務(wù),會包裝成一個FutureTask,F(xiàn)utureTask執(zhí)行用戶任務(wù),如果異常,不會對外拋出,僅是記錄,但是在調(diào)用Future.get時,會拋出異常。

          異常是在用戶線程中拋出的,因此不影響線程池中的線程。

          ScheduledThreadPoolExecutor.schedule

          源碼分析

          ScheduledThreadPoolExecutor.schedule會將用戶任務(wù)包裝為ScheduledFutureTask,ScheduledFutureTask是FutureTask的子類,看下ScheduledFutureTask的執(zhí)行邏輯

          圖片

          ScheduledFutureTask是FutureTask的子類,所以有異常時,也不是拋出,而是記錄

          • 293行對于非周期性任務(wù),執(zhí)行一次,如果有異常,不拋出,僅記錄
          • 294~296對于周期性任務(wù),執(zhí)行完本次后,會設(shè)置下次執(zhí)行的時間。如果本次出現(xiàn)異常,ScheduledFutureTask.super.runAndReset()返回結(jié)果為false(這個可以從源碼看到),此時不會設(shè)置下次任務(wù)調(diào)度的時間了,因此會導(dǎo)致周期性任務(wù)失效的現(xiàn)象,并且異常信息不會拋出,也不會打印
          總結(jié)

          ScheduledThreadPoolExecutor.schedule提交的用戶任務(wù),如果出現(xiàn)異常,是不會拋出的,也不會打印。

          對于非周期性任務(wù)和周期性任務(wù),執(zhí)行異常,都沒有辦法感知(不拋出、看不到)。

          對于周期性任務(wù),任何一次調(diào)度時,任務(wù)出現(xiàn)異常,都會導(dǎo)致后續(xù)無法調(diào)度。

          因此,在使用這個線程池時,我們應(yīng)當保證用戶任務(wù)不會拋出異常到執(zhí)行線程,避免任務(wù)調(diào)度失效,和異常排查困難等問題。

          思考:ThreadPoolExecutor.execute發(fā)生異常時為什么要退出

          ThreadPoolExecutor.execute出現(xiàn)用戶任務(wù)異常時,為什么要退出當前線程,再重新創(chuàng)建一個線程呢?

          我思考了半天,覺得原因之一可能是:

          ThreadPoolExecutor的可以指定線程工廠,如果我的線程工廠是這樣的

          ThreadFactory threadFactory = new ThreadFactory() {
              @Override
              public Thread newThread(Runnable r) {
                  Thread thread = new Thread(r);
                  thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                      @Override
                      public void uncaughtException(Thread t, Throwable e) {
                          // 處理異常的邏輯
                      }
                  });
                  return thread;
              }
          };

          即在ThreadFactory創(chuàng)建線程時,指定了對未捕獲的異常的處理器。

          這種情況下,如果線程池不把發(fā)生異常的線程退出,可能會導(dǎo)致異常沒有走到用戶期望的邏輯上,因此需要將發(fā)生異常的線程退出,然后JVM調(diào)用UncaughtExceptionHandler。

          1. 工作中如何體現(xiàn)一個人的技術(shù)深度?

          2. SpringBoot + Flyway,自動化實現(xiàn)數(shù)據(jù)庫版本控制

          3. Kubernetes 缺少的多租戶功能,你可以通過這些方式實現(xiàn)

          4. 老板讓我牽頭搞ELK,我該如何確定ES的集群規(guī)模?

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號平臺更改了推送規(guī)則,如果不想錯過內(nèi)容,記得讀完點一下在看,加個星標,這樣每次新文章推送才會第一時間出現(xiàn)在你的訂閱列表里。

          “在看”支持小哈呀,謝謝啦

          瀏覽 22
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  影音先锋男人网站 | 国产在线精品色 | 日韩无码一区二区三 | 欧美性爱久久平台 | 久草福利在线视频 |