併發包引入的工具類不少方法都會拋出必定的異常,這些異常描述了任務在線程池中執行時發生的例外狀況,而一般這些例外須要應用程序進行捕捉和處理。html
例如在Future接口中有以下一個API:java
在前面的章節中描述了Future類的具體實現原理。這裏再也不討論,可是比較好奇的拋出的三個異常。網絡
這裏有一篇文章(Java 理論與實踐: 處理 InterruptedException)描述了InterruptedException的來源和處理方式。簡單的說就是線程在執行的過程當中被本身或者別人中斷了。這時候爲了響應中斷就須要處理當前的異常。併發
對於java.lang.Thread而言,InterruptedException也是一個很詭異的問題。工具
中斷一個線程Thread.interrupt()時會觸發下面一種狀況:測試
若是線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程當中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException。ui
檢測一個線程的中斷狀態描述是這樣的Thread.interrupted():.net
測試當前線程是否已經中斷。線程的中斷狀態 由該方法清除。換句話說,若是連續兩次調用該方法,則第二次調用將返回 false(在第一次調用已清除了其中斷狀態以後,且第二次調用檢驗完中斷狀態前,當前線程再次中斷的狀況除外)。 線程
也就是說若是檢測到一個線程已經被中斷了,那麼線程的使用方(掛起、等待或者正在執行)都將應該獲得一箇中斷異常,同時將會清除異常中斷狀態。htm
上面獲取任務結果的方法實現中,將在獲取鎖的過程當中獲得一箇中斷異常。代碼java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(int, long)描述了這種狀況:
這裏在獲取鎖的時候檢測線程中斷狀況,若是被中斷則清除中斷位,同時拋出一箇中斷異常。爲何如此作?由於咱們的線程在線程池中是被重複執行的,因此一旦線程被中斷後並不會退出線程,而是設置中斷位,等候任務隊列本身處理線程,從而達到線程被重複利用的目的。有興趣的能夠參考代碼java.util.concurrent.ThreadPoolExecutor.Worker.runTask(Runnable)。這裏在關閉線程池時就會致使中斷全部線程。
除了InterruptedException 異常咱們還發現了一個全新的異常java.util.concurrent.TimeoutException,此異常是用來描述任務執行時間超過了指望等待時間,也許是一直沒有獲取到鎖,也許是尚未執行完成。
在innerGet代碼片斷中咱們看到,若是線程在指定的時間沒法獲取到鎖,那麼就會獲得一個超時異常。這個很好理解,好比若是執行一個很是耗時的網絡任務,咱們不但願任務一直等待從而佔用大量的資源,可能在必定時間後就會但願取消此操做。此時超時異常很好的描述了這種需求。
與此同時,若是取消了一個任務,那麼再次從任務中獲取執行結果,那麼將會獲得一個任務被取消的異常java.util.concurrent.CancellationException。
除了上述異常外,還將獲得一個java.util.concurrent.ExecutionException異常,
這是由於咱們的提交的任務java.util.concurrent.Callable在call()方法中容許拋出任何異常,另外常規的線程執行也可能拋出一個RuntimeException,因此這裏簡單包裝了下全部異常,看成執行過程當中發生的異常ExecutionException拋出。
以上就是整個異常體系,全部併發操做的異常均可以歸結於上述幾類。
不少狀況下處理時間長度都是用java.util.concurrent.TimeUnit,這是一個枚舉類型,用來描述時間長度。其中內置了一些長度的單位。其中包括納秒、微秒、毫秒、秒、分、時、天。例如超時操做5秒,可使用
Future.get(5,TimeUnit.SECONDS) 或者 Future.get(5000L,TimeUnit.MILLISECONDS)
固然一種單位的時間轉換成另外一種單位的時間也是很是方便的。另外還有線程的sleep/join以及對象的wait操做的便捷操做。