通常如下情況會取消:
1. 使用者發起取消請求
2. 現實的活動
3. 分解任務其中一條發現了解決方案,其他的就可以取消了
4. 分解任務其中一條發現了對于其他任務都有影響的錯誤,比如磁盤空間已滿,其他的可以取消了
5. 關閉, 當執行器關閉的時候,必須對正在處理及等待處理的任務進行優雅的關閉。
一個最簡單的方式是,加上取消标記,cancel方法設定取消标記。 主流程中判斷取消标記,進行操作
這樣有個問題,如果dosomthing()的時候有阻塞,就永遠不會監測到cancel的狀态, 在jdk中我們還能使用專門為了取消而存在的中斷方法。
上面的代碼就會改為這樣:
這裡再來看一個用法,使用逾時加上中斷來決定任務執行多久:
中斷政策
給線程加中斷有一個原則就是一定要清楚中斷政策,否則就不要使用中斷方法。
使用future完成取消
例如:
其中斷政策為:
.cancel(true),表示如果運作嘗試對目前線程進行中斷,一般是調用目前線程的.interrupt()方法
.cancel(false),表示如果沒運作則不會運作這個線程了,如果運作了,會等到運作完成。
比如生産者消費者模式。
因為其使用了take()阻塞的方法,能夠響應中斷,是以如果生産者阻塞了不是問題,但是這樣中斷可能不太好。
我們可以加入狀态标志,當設定了關閉标志之後,再生産就會抛出異常, 這個跟executor的shutdown方法是一樣的。
還有一種方式是使用緻命藥丸,就是在隊列中加入一個特殊的任務,執行到這個藥丸就停止服務。
使用trackingexecutor類還能夠擷取已經取消了的任務, 用exec.getcancelledtasks()來擷取
任務中的異常處理
在executors.newfixedthreadpool(int , threadfactory threadfactory)中的第二個構造參數,是當一個線程異常中斷的時候從這個factory中建立新的線程補充進去,可以用來做異常處理
或者一般情況下,使用future.get方法可以得到異常
正常關閉,system.exit()可以注冊關閉鈎子如下:
背景線程
daemon的線程,不會影響線程的退出。不會執行finally塊,通常用于内部的事務處理。
避免使用finalizer.不提供任何保證,并且會帶來巨大的性能開銷。