在TimeoutException之后如何让FutureTask返回?

del*_*ber 9 java futuretask

在下面的代码中,我按照预期在100秒后捕获TimeoutException.此时我希望代码退出main并终止程序,但它会继续打印到控制台.如何让任务在超时后停止执行?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    FutureTask<T> task = new FutureTask<T>(c);
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {

    try {
        int returnCode = timedCall(new Callable<Integer>() {
            public Integer call() throws Exception {
                for (int i=0; i < 1000000; i++) {
                    System.out.println(new java.util.Date());
                    Thread.sleep(1000);
                }
                return 0;
            }
        }, 100, TimeUnit.SECONDS);
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }


}
Run Code Online (Sandbox Code Playgroud)

Ale*_*nov 10

您需要在超时时取消任务(并中断其线程).那是什么cancel(true)方法.:

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {
        try {
            FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
                public Integer call() throws Exception {
                        for (int i=0; i < 1000000; i++) {
                                if (Thread.interrupted()) return 1;
                                System.out.println(new java.util.Date());
                                Thread.sleep(1000);
                        }
                        return 0;
                }
            });
            int returnCode = timedCall(task, 100, TimeUnit.SECONDS);
        } catch (Exception e) {
                e.printStackTrace();
                task.cancel(true);
        }
        return;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为使用中断要好得多。首先,您的可调用代码根本不需要了解 `task`。其次,当你在你的可调用代码中使用各种阻塞操作(比如 `Thread.sleep()`)时,这些操作不会对 task.isCancelled() 做出反应,但通常会对中断做出反应。因此,使用 `cancel(true)` 并使你的代码意识到中断通常是最好的方法。(你的代码也会更通用,因为中断机制在 Java 中被广泛使用) (2认同)