
【疑问】
Future有一个cancel(mayInterruptIfRunning)方法。
mayInterruptIfRunning代表什么意思呢?它的值会影响任务的中断吗?
【分析】
1. FutureTask中线程的运行状态
/*
* Possible state transitions:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
下图是线程的生命周期,可以看到和代码中的状态不是一回事情。

FutureTask的生命周期是怎样的呢,它和线程的生命周期有没有共通之处呢?

- New状态:线程生命周期的New状态,Runnable状态,blocked状态;
- Completing状态:线程生命周期的Running状态;
- normal、exceptional、cancelled、interrupted状态:线程生命周期的Terminated状态;
使用FutureTask执行Task()线程逻辑:
//创建FutureTask实例
FutureTask futureTask = new FutureTask(new Task());
//执行FutureTask
new Thread(futureTask).start();
2. 线程的中断方法
FutureTask不为New状态,那么直接返回false。
若status状态为New。
2.1参数mayInterruptIfRunning=false,任务不会被中断,并且任务的状态为cancelled(FutureTask的终态)。
2.2 参数mayInterruptIfRunning=true,status状态会变为interrupting,FutrueTask中的线程会调用interrupt()方法,(若线程为Running状态,则会变更isInterrupted标志位。若线程为Blocking状态,则会抛出异常,终止线程)。接着会变更为interrupted(FutureTask的终态)。
源码:java.util.concurrent.FutureTask#cancel
public boolean cancel(boolean mayInterruptIfRunning) {
// 1. 判断
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
//调用Thread
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
以线程角度考虑:
线程为New状态时调用cancel方法,无论参数如何FutureTask的status均是终态。故即使调用线程的start方法,线程也不会执行,故为中断。
线程为Runnable或blocking状态时,cancel参数为true时便可执行thread的interrupt方法。线程会捕获中断异常,进而结束线程。
线程为running状态时,FutureTask为completing状态。interrupt无法中断正在持有cpu资源的线程,故方法直接返回false。
附录
UNSAFE.compareAndSwapInt(this, valueOffset, expect,update)
CAS的比较算法,原理就是通过比较预期值expect和主存中的valueOffset是否相等,若不相等返回false,若相等,则使用update更新主存中的valueOffset值。
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
将interrupted状态刷新到主存中。