天天看點

并發程式設計7 - 任務取消

通常如下情況會取消:

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.不提供任何保證,并且會帶來巨大的性能開銷。