FutureTask的cancel方法真的能停止掉一个正在执行的异步任务吗

FutureTask的cancel方法真的能停止掉一个正在执行的异步任务吗ExecutorServiceexecutor=Executors.newSingleThreadExecutor();FutureTask<?>futureTask=newFutureTask<String>(newCallable<String>(){@OverridepublicStringcall()throwsException{…

        ExecutorService executor = Executors.newSingleThreadExecutor();
        FutureTask<?> futureTask = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {

                for(int i=0;i<10000;i++){

                    System.out.println(i);
                }
                return null;
            }
        });
        executor.execute(futureTask);
        System.out.println(“futureTask start”);
        try {

            Thread.sleep(10);
        } catch (InterruptedException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        futureTask.cancel(true);
        System.out.println(“futureTask cancel”);
    }
我们先来看看这个例子,发现最终执行结果是9999,即异步任务并没有被cancel而是一直执行完毕,这样看来这个cancel方法有点名不副实啊。

其实我们如果查看FutureTask的源码就会发现cancel只不过是调用了Thread的interrupt方法,而interrupt只能是停掉线程中有sleep,wait,join逻辑的线程,抛出一个InterruptException。

为什么弃用stop:

  1. 调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
  2. 调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

这样看来FutureTask的cancel方法并不能停掉一切正在执行的异步任务。但是这里我们有一个妥协的做法就是在判断条件中加!Thread.currentThread().isInterrupted()这个判断即可

ExecutorService executor = Executors.newSingleThreadExecutor();
        FutureTask<?> futureTask = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {

                for(int i=0;i<10000&&!Thread.currentThread().isInterrupted();i++){

                    System.out.println(i);
                }
                return null;
            }
        });
        executor.execute(futureTask);
        System.out.println(“futureTask start”);
        try {

            Thread.sleep(10);
        } catch (InterruptedException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        futureTask.cancel(true);
        System.out.println(“futureTask cancel”);

最终这个就可以真正的结束异步任务。
  到这里我们可以发现Java中并没有可以真正中断线程的方法,早期的stop已经不推荐使用,而interrupt方法也需要代码片段中有sleep,wait,join这些方法的调用,否则不能停止线程,现在java推荐的方式就是将run方法执行完,这就需要我们在while循环中加一个标志来控制退出,不过我们不需要额外设置这个标志,只需要调用thread的isInterrupted()方法判断,这样外界就可以调用该线程的isInterrupted方法来停止现在了,不用额外添加标志。
————————————————
版权声明:本文为CSDN博主「宇宙小生命」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/stephen8341/article/details/50433656

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/38759.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注