在执行者中延时执行任务

Executor 框架提供了 ThreadPoolExecutor 类用一个线程池来执行 Callable 和 Runnable 任务,避免了所有这些线程创建的操作。 当您将一个任务发送到执行者,它将根据执行者的配置尽快执行。在某些使用场景您不想尽快执行。如可能想过一段时间再执行或周期性地执行。 为此,Executor 框架提供了 ScheduledThreadPoolExecutor 类。

任务

延时执行几个任务.

实现

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

  • Callable<String> 类: Task

    • 属性 name : String对象
    • 构造函数初始化属性为参数值
        private String name;
    
        public Task(String name) {
            this.name = name;
        }
    
    • call() 方法 : 在终端输出当前时间等信息
        @Override
        public String call() throws Exception {
            System.out.printf("%s: Starting at : %s\n",name,new Date());
            return "Hello, world";
        }
    
  • 控制类 : Main

    • 使用 Executors 类的 newScheduledThreadPool() 方法创建一个 ScheduledThreadPoolExecutor ,传递 1 作为参数
        ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
    
    • 使用 ScheduledThreadPoolExecutor 实例的 schedule() 方法初始化并启动几个任务
        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);
        }
    
    • 使用 shutdown() 方法结束执行者的执行
        executor.shutdown();
    
    • 使用 executor 的 awaitTermination() 方法等待所有任务的结束
        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个参数:

  • 想执行的任务
  • 在执行前要等待的时间段
  • 时间段的单位,由 TimeUnit 类的常量指定

本例中,每个任务将等待它在数组中的位置+1秒后再执行。

如果您想在一个给定的时间执行一个任务,计算该时间与当前时间的差距并用此差距作为任务的延期时间

了解更多

您也能用 Runnable 接口来实现任务,因为 ScheduledThreadPoolExecutor 类的 schedule() 方法接受2种类型的任务。

尽管 ScheduledThreadPoolExecutor 类是 ThreadPoolExecutor 类的一个子类,也因此继承了它的所有特性,Java 建议只用其创建计划任务。

您可以配置在调用 shutdown() 方法且有待完成的任务在等待延时执行时 ScheduledThreadPoolExecutor 的行为。 缺省行为是那些任务将不管执行者的结束而将被执行。 您可以用 ScheduledThreadPoolExecutor 类的 setExecuteExistingDelayedTasksAfterShutdownPolicy() 方法来改变此行为。 如果参数为 false,待处理的任务将不会执行。