java併發程式設計實戰:取消與關閉筆記
阿新 • • 發佈:2019-01-12
在Java中無法搶佔式地停止一個任務的執行,而是通過中斷機制實現了一種協作式的方式來取消任務的執行。
設定取消標誌
public class MyTask implements Runnable {
private final ArrayList<BigInteger> primes = new ArrayList<BigInteger>();
private volatile boolean cancelled;
@Override
public void run() {
while (!cancelled) {
...
}
}
public void cancel() {
cancelled = true;
}
}
中斷執行緒的執行
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
interrupt方法試圖中斷執行緒並設定中斷狀態標誌變數為true;
isInterrupted方法測試執行緒是否已經中斷,返回中斷狀態變數的值;
interrupted方法用於清除執行緒的中斷狀態,並返回之前的值,即如果當前執行緒是中斷狀態,則重新設定為false,並且返回true;
呼叫interrupt並不意味著必然停止目標執行緒工作,它緊緊傳遞了請求中斷資訊。
阻塞方法與執行緒的中斷
大部分的阻塞方法都是響應中斷的,即這些方法線上程中執行時如果發現執行緒被中斷,會清除執行緒的中斷狀態,並丟擲InterruptedException表示該方法的執行過程被從外部中斷。響應中斷的阻塞方法通常會在入口處先檢查執行緒的中斷狀態,執行緒不是中斷狀態時,才會繼續執行。
class PrimeProducer extends Thread{
private final BlockingQueue<BigInteger> queue;
private volatile boolean cancelled;
PrimeProducer(BlockingQueue<BigInteger> queue){
this.queue = queue;
}
public void run(){
BigInteger p = BigInteger.ONE;
while(!Thread.currentThread().isInterrupted(){
queue.put(p = p.nextProbablePrime());
}catch(InterruptedException consumed){
/*允許執行緒退出*/
}
}
public void cancel(){
interrupt();
}
}
中斷響應
當呼叫可中斷的阻塞方法時,有兩種策略可用於處理InterruptedException
1、傳遞異常,從而使你的方法也成為可中斷的阻塞方法。
2、恢復中斷狀態,從而使呼叫棧上中的上層程式碼能夠對其進行處理。
只有實現了執行緒中斷策略的程式碼才可以遮蔽中斷請求,常規任務中不應該遮蔽中斷請求。
通過Future實現取消
public class TimedRun {
private static final ExecutorService taskExec = Executors.newCachedThreadPool();
public static void timedRun(Runnable r,
long timeout, TimeUnit unit)
throws InterruptedException {
Future<?> task = taskExec.submit(r);
try {
task.get(timeout, unit);
} catch (TimeoutException e) {
// task will be cancelled below
} catch (ExecutionException e) {
// exception thrown in task; rethrow
throw launderThrowable(e.getCause());
} finally {
// Harmless if task already completed
task.cancel(true); // interrupt if running
}
}
}
Future介面有一個cancel方法,可以通過該方法取消任務的執行,cancel方法有一個boolean型的引數mayInterruptIfRunning。
如果設定為false,對於正在執行的任務只能等到任務執行完畢,無法中斷;
如果設定為true,對於正在執行的任務可以試圖中斷任務的執行,這種情況通常只在與Executor框架配合時使用,因為執行任務的執行緒是由Executor建立的,Executor知道該如何中斷執行任務的執行緒;