繁体   English   中英

Future.cancel(boolean)方法的实用程序

[英]Utility of Future.cancel(boolean) method

我只是在探索java.util.concurrent包。

我了解到类' Future '有一个方法boolean cancel(boolean mayInterruptIfRunning)

请查找附上我写的测试代码:

package com.java.util.concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;

public class FutureTester {

/**
 * @param args
 * @throws InterruptedException
 */
public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    int poolCnt = 1;
    Callable<NumberPrinter> numberPrinter = null;
    ScheduledThreadPoolExecutor schPool = new ScheduledThreadPoolExecutor(
            poolCnt);
    ScheduledFuture<NumberPrinter>[] numPrinterFutures = new ScheduledFuture[poolCnt];
    FutureTask<NumberPrinter>[] futureTask = new FutureTask[poolCnt];

    for (int i = 0; i < poolCnt; i++) {
        numberPrinter = new NumberPrinter();
        futureTask[i] = new FutureTask<NumberPrinter>(numberPrinter);

        /*
         * numPrinterFutures[i] = (ScheduledFuture<NumberPrinter>) schPool
         * .schedule(futureTask[i], 0, TimeUnit.MILLISECONDS);
         */
        numPrinterFutures[i] = (ScheduledFuture<NumberPrinter>) schPool
                .submit(futureTask[i]);
    }

    //Thread.sleep(30);

    if (numPrinterFutures.length > 0) {

        System.out.println("Task completed ? "
                + numPrinterFutures[0].isDone());

        System.out.println("Task cancelled ? "
                + numPrinterFutures[0].cancel(true));

        System.out.println("Is task cancelled ? "
                + numPrinterFutures[0].isCancelled());
    }
}

}

class NumberPrinter implements Callable<NumberPrinter> {

private int counter = 10;

@Override
public NumberPrinter call() throws Exception {
    // TODO Auto-generated method stub

    while (counter > 0) {
        if (Thread.interrupted()) {/*OUCH !!!*/
            return null;
        }
        System.out.println("counter = " + (counter--));
    }

    return this;
}

}

最初,我假设取消任务也将停止正在运行的线程的执行( 不包括'OUCH'部分 )。但是我得到如下输出:

counter = 10
Task completed ? false
counter = 9
Task cancelled ? true
counter = 8
Is task cancelled ? true
counter = 7
counter = 6
counter = 5
counter = 4
counter = 3
counter = 2
counter = 1

关于stackoverflow本身的进一步阅读,有人说

  1. 'cancel'方法只能停止'unstarted'作业(与方法的api描述相矛盾)
  2. cancel方法只是中断正在运行的线程,然后必须从run()方法返回

因此,我包括'OUCH'部分 - 一个while循环检查中断 ;输出如下:

Task completed ? false
counter = 10
Task cancelled ? true
Is task cancelled ? true

题 :

如果应该写一个类似于'OUCH'部分的东西来停止正在运行的线程,那么cancel方法的效用/值是多少。 如果无法通过取消停止线程,如何在FutureTask中包装Callable有用? 我忽视的设计/概念/逻辑部分是什么?

如果无法通过取消停止线程,如何在FutureTask中包装Callable有用?

您想要取消任务,而不是运行它的线程。 使用cancel(true)可防止任务启动(但不会将其从队列中删除),并在任务启动时中断线程。 Task可以忽略中断,但没有杀死整个进程的干净方法。

您忽视的问题是只能在Java中安全地停止协作线程。

实际上,如果你看一下Thread API,你会发现在Java 1.1中有一些叫做destroypausestopresume方法。 他们被弃用的原因是Java设计者意识到他们通常不能安全使用。 原因在注释“为什么Thread.stop,Thread.suspend和Thread.resume已弃用?”中进行了解释。

这个问题是Java线程模型中固有的问题,只能通过限制一个线程与其他线程使用的对象进行交互的能力来避免。 有一个JSR指定了这样做的一种方式......隔离......但据我所知,没有主流JVM实现这些API。


因此,回到你的问题, Future.cancel的用处在于它解决了可以在期货背景下解决的问题子集。

调用cancel(true)将阻止Future执行(如果尚未运行),并且如果当前正在运行则将被interrupted 此时,取消Future的负担将由开发人员承担。

因为它是一个线程池,所以停止该线程是没有意义的(尽管停止一个线程很少有意义)。 取消/中断不会导致线程退出其run方法。 在执行Callable的调用方法之后,它将简单地从工作队列中拉出下一个项目并进行处理。

cancel方法的实用程序只是向执行线程发出信号,表示某个进程想要Callable停止 - 而不是线程 - 所以你必须自己处理Callable的停止。

假设,作为您未来的一部分运行的代码不支持合作取消或中断。 然后取消未启动的任务是您可能做的最好的事情。 这就是存在这种方法的原因。

总的来说,我认为取消是严格合作的。 只需用力取消某些代码就可能导致状态损坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM