美文网首页并发编程
FutureTask的cancel方法真的能终止正在运行的线程吗

FutureTask的cancel方法真的能终止正在运行的线程吗

作者: 小胖学编程 | 来源:发表于2019-08-26 11:07 被阅读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刷新到主存中。

    相关文章

      网友评论

        本文标题:FutureTask的cancel方法真的能终止正在运行的线程吗

        本文链接:https://www.haomeiwen.com/subject/cqqrectx.html