Executor 框架提供了 ThreadPoolExecutor 类用一个线程池来执行 Callable 和 Runnable 任务,避免了所有这些线程创建的操作。 当您将一个任务发送到执行者,它将根据执行者的配置尽快执行。在某些使用场景您不想尽快执行。如可能想过一段时间再执行或周期性地执行。 为此,Executor 框架提供了 ScheduledThreadPoolExecutor 类。
本节的示例代码在 com.elanzone.books.noteeg.chpt4.sect07 package中
Callable<String> 类: Task
private String name; public Task(String name) { this.name = name; }
@Override public String call() throws Exception { System.out.printf("%s: Starting at : %s\n",name,new Date()); return "Hello, world"; }
控制类 : Main
ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
System.out.printf("Main: Starting at: %s\n", new Date()); for (int i = 0; i < 5; i++) { Task task = new Task("Task " + i); executor.schedule(task, i + 1, TimeUnit.SECONDS); }
executor.shutdown();
try { executor.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Main: Ends at: %s\n", new Date());
本例的关键在于 Main 类和 ScheduledThreadPoolExecutor 的管理。 如同 ThreadPoolExecutor 类,Java 建议使用 Executors 类来创建一个计划执行者。 本例中,用了 newScheduledThreadPool() 方法。传递了数字 1 作为此方法的参数。此参数是线程池里的线程数。
为了在一段时间后在计划执行者中执行一个任务,您必须使用 schedule() 方法。此方法接受以下3个参数:
本例中,每个任务将等待它在数组中的位置+1秒后再执行。
如果您想在一个给定的时间执行一个任务,计算该时间与当前时间的差距并用此差距作为任务的延期时间
您也能用 Runnable 接口来实现任务,因为 ScheduledThreadPoolExecutor 类的 schedule() 方法接受2种类型的任务。
尽管 ScheduledThreadPoolExecutor 类是 ThreadPoolExecutor 类的一个子类,也因此继承了它的所有特性,Java 建议只用其创建计划任务。
您可以配置在调用 shutdown() 方法且有待完成的任务在等待延时执行时 ScheduledThreadPoolExecutor 的行为。 缺省行为是那些任务将不管执行者的结束而将被执行。 您可以用 ScheduledThreadPoolExecutor 类的 setExecuteExistingDelayedTasksAfterShutdownPolicy() 方法来改变此行为。 如果参数为 false,待处理的任务将不会执行。