xylz,imxylz

          關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

             :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks

          并發(fā)包引入的工具類很多方法都會拋出一定的異常,這些異常描述了任務(wù)在線程池中執(zhí)行時發(fā)生的例外情況,而通常這些例外需要應(yīng)用程序進行捕捉和處理。

          例如在Future接口中有如下一個API:

           

          java.util.concurrent.Future.get(long, TimeUnit) throws InterruptedException, ExecutionException, TimeoutException;

           

          前面的章節(jié)中描述了Future類的具體實現(xiàn)原理。這里不再討論,但是比較好奇的拋出的三個異常。

          這里有一篇文章(Java 理論與實踐: 處理 InterruptedException)描述了InterruptedException的來源和處理方式。簡單的說就是線程在執(zhí)行的過程中被自己或者別人中斷了。這時候為了響應(yīng)中斷就需要處理當(dāng)前的異常。

          對于java.lang.Thread而言,InterruptedException也是一個很詭異的問題。

          中斷一個線程Thread.interrupt()時會觸發(fā)下面一種情況:

          如果線程在調(diào)用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程中受阻,則其中斷狀態(tài)將被清除,它還將收到一個 InterruptedException。

          檢測一個線程的中斷狀態(tài)描述是這樣的Thread.interrupted():

          測試當(dāng)前線程是否已經(jīng)中斷。線程的中斷狀態(tài) 由該方法清除。換句話說,如果連續(xù)兩次調(diào)用該方法,則第二次調(diào)用將返回 false(在第一次調(diào)用已清除了其中斷狀態(tài)之后,且第二次調(diào)用檢驗完中斷狀態(tài)前,當(dāng)前線程再次中斷的情況除外)。 

          也就是說如果檢測到一個線程已經(jīng)被中斷了,那么線程的使用方(掛起、等待或者正在執(zhí)行)都將應(yīng)該得到一個中斷異常,同時將會清除異常中斷狀態(tài)。

           

          V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
              
          if (!tryAcquireSharedNanos(0, nanosTimeout))
                  
          throw new TimeoutException();
              
          if (getState() == CANCELLED)
                  
          throw new CancellationException();
              
          if (exception != null)
                  
          throw new ExecutionException(exception);
              
          return result;
          }

           

          上面獲取任務(wù)結(jié)果的方法實現(xiàn)中,將在獲取鎖的過程中得到一個中斷異常。代碼java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(int, long)描述了這種情況:

              public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
              
          if (Thread.interrupted())
                  
          throw new InterruptedException();
              
          return tryAcquireShared(arg) >= 0 ||
                  doAcquireSharedNanos(arg, nanosTimeout);
              }

           


          這里在獲取鎖的時候檢測線程中斷情況,如果被中斷則清除中斷位,同時拋出一個中斷異常。為什么如此做?因為我們的線程在線程池中是被重復(fù)執(zhí)行的,所以一旦線程被中斷后并不會退出線程,而是設(shè)置中斷位,等候任務(wù)隊列自己處理線程,從而達到線程被重復(fù)利用的目的。有興趣的可以參考代碼java.util.concurrent.ThreadPoolExecutor.Worker.runTask(Runnable)。這里在關(guān)閉線程池時就會導(dǎo)致中斷所有線程。

          除了InterruptedException 異常我們還發(fā)現(xiàn)了一個全新的異常java.util.concurrent.TimeoutException,此異常是用來描述任務(wù)執(zhí)行時間超過了期望等待時間,也許是一直沒有獲取到鎖,也許是還沒有執(zhí)行完成。

          在innerGet代碼片段中我們看到,如果線程在指定的時間無法獲取到鎖,那么就會得到一個超時異常。這個很好理解,比如如果執(zhí)行一個非常耗時的網(wǎng)絡(luò)任務(wù),我們不希望任務(wù)一直等待從而占用大量的資源,可能在一定時間后就會希望取消此操作。此時超時異常很好的描述了這種需求。

          與此同時,如果取消了一個任務(wù),那么再次從任務(wù)中獲取執(zhí)行結(jié)果,那么將會得到一個任務(wù)被取消的異常java.util.concurrent.CancellationException。

          除了上述異常外,還將得到一個java.util.concurrent.ExecutionException異常,

          這是因為我們的提交的任務(wù)java.util.concurrent.Callable在call()方法中允許拋出任何異常,另外常規(guī)的線程執(zhí)行也可能拋出一個RuntimeException,所以這里簡單包裝了下所有異常,當(dāng)作執(zhí)行過程中發(fā)生的異常ExecutionException拋出。

          以上就是整個異常體系,所有并發(fā)操作的異常都可以歸結(jié)于上述幾類。

          很多情況下處理時間長度都是用java.util.concurrent.TimeUnit,這是一個枚舉類型,用來描述時間長度。其中內(nèi)置了一些長度的單位。其中包括納秒、微秒、毫秒、秒、分、時、天。例如超時操作5秒,可以使用

          Future.get(5,TimeUnit.SECONDS) 或者 Future.get(5000L,TimeUnit.MILLISECONDS)

          當(dāng)然一種單位的時間轉(zhuǎn)換成另一種單位的時間也是非常方便的。另外還有線程的sleep/join以及對象的wait操作的便捷操作。

           



          ©2009-2014 IMXYLZ |求賢若渴
          posted on 2011-07-12 23:15 imxylz 閱讀(17418) 評論(3)  編輯  收藏 所屬分類: Java Concurrency

          評論

          # re: 深入淺出 Java Concurrency (36): 線程池 part 9 并發(fā)操作異常體系 2011-07-15 08:48 gameboy120
          終于又有新文章了,博主最近很忙啊  回復(fù)  更多評論
            

          # re: 深入淺出 Java Concurrency (36): 線程池 part 9 并發(fā)操作異常體系[未登錄] 2011-07-19 20:33 楊羅羅
          一直在看,許多線程類文章寫的很深入,值得研究  回復(fù)  更多評論
            

          # re: 深入淺出 Java Concurrency (36): 線程池 part 9 并發(fā)操作異常體系 2011-08-18 18:10 yintiefu
          樓主的這個系列看了幾天終于看完了啊!非常感謝   回復(fù)  更多評論
            


          ©2009-2014 IMXYLZ
          主站蜘蛛池模板: 永吉县| 海晏县| 静安区| 获嘉县| 沙河市| 会同县| 马关县| 伊宁县| 蒲城县| 喀喇沁旗| 随州市| 都江堰市| 吉木乃县| 五常市| 辽源市| 乌兰浩特市| 常德市| 安庆市| 杨浦区| 图木舒克市| 延川县| 桃源县| 天镇县| 岚皋县| 宁津县| 科技| 威信县| 天台县| 若尔盖县| 中阳县| 新泰市| 门头沟区| 大悟县| 沙田区| 秦皇岛市| 南康市| 蒙山县| 息烽县| 绵竹市| 施甸县| 美姑县|