在执行者中取消任务

使用一个 executor,您不必管理线程。只需要实现 Runnable 或 Callable 任务并发给 executor。 executor负责创建线程、在线程池中管理、如果不再需要则结束它们。 有时您想取消一个已送去 executor 的任务。此时可使用 Future 的 cancel() 方法来执行取消操作。

任务

使用 cancel() 方法取消已送去 executor 的任务。

实现

本节的示例代码在 com.elanzone.books.noteeg.chpt4.sect09 package中

  • Callable<String> 类: Task

    • 在call方法中无限循环,每次循环输出信息到终端并睡上 100 毫秒
    public class Task implements Callable<String> {
    
        @Override
        public String call() throws Exception {
            while (true){
                System.out.printf("Task: Test\n");
                Thread.sleep(100);
            }
        }
    
    }
    
  • 控制类 : Main

    • 使用 Executors 类的 newCachedThreadPool() 方法创建一个 ThreadPoolExecutor
        ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();
    
    • 创建一个新 Task 对象并用 submit() 方法将其发给 executor 执行
        Task task = new Task();
    
        System.out.printf("Main: Executing the Task\n");
        Future<String> result = executor.submit(task);
    
    • 睡上 2 秒
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
    • 使用 submit() 方法返回的 Future 对象的 cancel() 方法取消任务的执行。cancel() 方法参数传 true。
        System.out.printf("Main: Canceling the Task\n");
        result.cancel(true);
    
    • 将 isCancelled() 方法和 isDone() 方法调用的结果输出到终端, 以验证线程是否已被取消, 从而已结束.
        System.out.printf("Main: Canceled: %s\n", result.isCancelled());
        System.out.printf("Main: Done: %s\n",result.isDone());
    
    • 调用 shutdown() 方法结束 executor
        executor.shutdown();
        System.out.printf("Main: The executor has finished\n");
    

工作原理

根据 cancel() 方法的参数和任务的状态,此方法的行为不一样:

  • 如果任务已结束 或 之前已被取消 或 因为其他原因不能被取消,此方法将返回 false ,任务不会被取消
  • 如果任务在执行者中等待获得一个线程对象来执行它,此任务被取消并不能开始执行。
  • 如果任务已在运行,则依赖此方法的参数。(cancel()方法有一个 Boolean 类型的参数)
    • 如果参数值为 true,任务将被取消
    • 如果参数值为 false,任务不会被取消

了解更多

如果使用一个所控制任务已被取消的 Future 对象的 get() 方法,get() 方法将抛出一个 CancellationException 异常。