Executor 框架提供了 ThreadPoolExecutor 类用一个线程池来执行 Callable 和 Runnable 任务,避免了所有这些线程创建的操作。 当您将一个任务发送到执行者,它将根据执行者的配置尽快执行。 当它结束,任务从执行者处被删除。如果您想再次执行,您必须将其再次发给执行者。
Executor 框架通过 ScheduledThreadPoolExecutor 类提供了执行周期性的任务的可能性。
本节的示例代码在 com.elanzone.books.noteeg.chpt4.sect08 package中
Runnable 实现类 : Task
public class Task implements Runnable { private String name; public Task(String name) { this.name = name; } @Override public void run() { System.out.printf("%s: Starting at : %s\n", name, new Date()); } }
控制类 : Main
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
System.out.printf("Main: Starting at: %s\n", new Date()); Task task = new Task("Task"); ScheduledFuture<?> result = executor.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);
for (int i = 0; i < 10; i++) { System.out.printf("Main: Delay: %d\n", result.getDelay(TimeUnit.MILLISECONDS)); try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } }
executor.shutdown();
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Main: Finished at: %s\n", new Date());
当要用 Executor 框架执行一个周期任务,需要一个 ScheduledExecutorService 对象。 Java 推荐使用 Executors 类来创建它。Executors 类作为一个执行者对象的工厂类。 在本例中,应使用 newScheduledThreadPool() 方法来创建一个 ScheduledExecutorService 对象。 此方法接受线程池中线程数目作为一个参数。因为本例中只有一个任务,所以参数值为 1。
有了执行一个周期任务所需的执行者,就可以发送任务到此执行者。本例中使用了 scheduledAtFixedRate() 方法。 此方法接受 4 个参数:
两次执行之间的时长是这两次执行 开始时间 的间隔时长。如果您有一个周期任务持续 5 秒而间隔时间是 3 秒,每次将有2个任务的实例运行。
scheduleAtFixedRate() 方法返回一个 ScheduledFuture 对象,ScheduledFuture 扩展 Future 接口,有一些方法干计划任务的活。 ScheduledFuture 是一个参数化的接口。本例中,因为任务是一个没有参数化的 Runnable 对象,所以必须用 ? 符号作为参数来参数化它。
您已使用了 ScheduledFuture 接口的一个方法。getDelay() 方法返回离任务的下一次执行的时间。 此方法接受一个 TimeUnit 常量,返回结果将以此常量作为单位。
ScheduledThreadPoolExecutor 提供了其他的方法来计划周期性任务。就是 scheduleWithFixedDelay() 方法。 它的参数和 scheduledAtFixedRate() 方法一致,但是其区别值得一提。
您也可配置 ScheduledThreadPoolExecutor 类的实例的 shutdown() 方法的行为。 默认行为是计划任务在调用 shutdown() 方法时结束。 您能使用 ScheduledThreadPoolExecutor 类的 setContinueExistingPeriodicTasksAfterShutdownPolicy() 方法改变此行为。 参数为 true 时,周期任务在调用 shutdown() 方法时不会结束。