FutureTask的cancel方法真的能终止正在运行的线程吗
2019-08-26 本文已影响0人
小胖学编程
Future的API
【疑问】
Future有一个cancel(mayInterruptIfRunning)方法。若任务正在执行,并且mayInterruptIfRunning设置为true,那么可以取消掉正在运行的线程吗?
【源码】
java.util.concurrent.FutureTask#cancel
1. 线程的声明周期变量
/*
* 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;
NEW:未运行状态,但是线程可能处于sleep,join,wait或未触发状态。
2. 线程的中断方法
public boolean cancel(boolean mayInterruptIfRunning) {
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方法返回false,即不能取消该线程的运行。
- 若是NEW状态(即sleep,wait,join等状态时),本质上是调用了Thread的interrupt()方法,进行中断的。
java中结束线程的方法总结
其实在java中没有真正可以中断线程调用的方法。
- 早期的stop方法因为过于暴力的中断线程,可能带来不可预知的异常,不推荐使用。
- interrupt方法也需要线程代码片段中有sleep,wait,join这些方法的调用,否则不能停止线程。
- 在线程的while循环中加入一个标志位来控制退出。(volatile修饰的变量,但是不推荐)。
- 调用thread的isInterrupted()方法判断。这样外界可以调用线程的 thread.interrupt();方法来控制线程的结束。
推荐阅读
UNSAFE.compareAndSwapInt(this, valueOffset, expect,update)
CAS的比较算法,原理就是通过比较预期值expect和主存中的valueOffset是否相等,若不相等返回false,若相等,则使用update更新主存中的valueOffset值。
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
将INTERRUPTED刷新到主存中。