当用执行器开发时,不需要管理线程,只要实现Runnable或Callable任务且发送给执行器。执行器的任务是创建线程,在线程池中管理线程,如果不需要的话则结束线程。有时可能会取消发送给执行器的任务,这种请款下, 使用Future的cancel()方法,允许你进行取消操作。本届中,学习如何使用此方法取消已经发送到执行器的任务。
准备工作
本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。
实现过程
通过如下步骤完成范例:
-
创建名为Task的类,实现String类参数化的Callable接口。实现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()方法的Main类:
public class Main { public static void main(String[] args) {
-
使用Executors类的newCachedThreadPool()方法创建ThreadPoolExecutor对象:
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
-
创建新的Task对象:
Task task = new Task();
-
使用submit()方法发送任务到执行器:
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(); }
-
使用Future对象的cancel()方法取消任务执行,这个Future对象名为result,通过submit()方法返回,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.shutdown(); System.out.printf("Main : The executor has finished\n");
工作原理
当需要取消已经发送到执行器的任务时,使用Future接口的cancel()方法。此方法的特性取决于传参值和任务状态的变化而不同:
- 如果任务已经完成或者之前已经被取消,或者因为其他任何原因而无法取消,此方法返回false值,且任务无法被取消。
- 如果任务在执行器中等待获得执行它的Thread对象,此任务将被取消且永不会执行。如果任务已经运行,则取决于此方法的参数。cancel()方法接受布尔值作为参数,如果参数值是true且任务正在运行,则将被取消。如果参数值是false且任务正在运行,则不会被取消。
下图显示本范例在控制台输出的执行信息:
扩展学习
如果使用Future对象的get()方法控制已经被取消的任务,get()方法将抛出CancellationException异常。
更多关注
本章“执行器中运行返回结果的任务“小节。