并发编程

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;
    }
  1. 若线程不是NEW状态,那么cancel方法返回false,即不能取消该线程的运行。
  2. 若是NEW状态(即sleep,wait,join等状态时),本质上是调用了Thread的interrupt()方法,进行中断的。

java中结束线程的方法总结

其实在java中没有真正可以中断线程调用的方法。

  1. 早期的stop方法因为过于暴力的中断线程,可能带来不可预知的异常,不推荐使用。
  2. interrupt方法也需要线程代码片段中有sleep,wait,join这些方法的调用,否则不能停止线程。
  3. 在线程的while循环中加入一个标志位来控制退出。(volatile修饰的变量,但是不推荐)。
  4. 调用thread的isInterrupted()方法判断。这样外界可以调用线程的 thread.interrupt();方法来控制线程的结束。

推荐阅读

  1. 源码导读-帮助篇-什么叫做CAS算法【图文版】
  2. 小小建议——多线程与并发(1)线程的创建和使用
 UNSAFE.compareAndSwapInt(this, valueOffset, expect,update)

CAS的比较算法,原理就是通过比较预期值expect和主存中的valueOffset是否相等,若不相等返回false,若相等,则使用update更新主存中的valueOffset值。

UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);

将INTERRUPTED刷新到主存中。

上一篇下一篇

猜你喜欢

热点阅读