Java ScheduledThreadPoolExecutor –使用ExecutorService进行计划

时间:2020-01-09 10:35:13  来源:igfitidea点击:

Java中的ScheduledThreadPoolExecutor添加了一些功能,以计划命令在给定延迟后运行或者定期执行。由于ScheduledThreadPoolExecutor是ExecutorService,因此它使用线程池中的线程执行任务。

Java ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor类是Java Executor框架的一部分,具有Java并发API。此类扩展了ThreadPoolExecutor并实现了ScheduledExecutorService接口。

Java ScheduledThreadPoolExecutor构造函数

  • ScheduledThreadPoolExecutor(int corePoolSize)–使用给定的核心池大小创建一个新的ScheduledThreadPoolExecutor。

  • ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler处理程序)–使用给定的初始参数创建一个新的ScheduledThreadPoolExecutor。

  • ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory)–使用给定的初始参数创建一个新的ScheduledThreadPoolExecutor。

  • ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler处理程序)–使用给定的初始参数创建一个新的ScheduledThreadPoolExecutor。

ScheduledThreadPoolExecutor类的这些构造函数中使用的参数如下:

  • corePoolSize –要保留在池中的线程数。这些线程数即使处于空闲状态也将始终被创建,除非设置allowCoreThreadTimeOut。

  • threadFactory –执行程序创建新线程时要使用的工厂。

  • handler –因达到线程边界和队列容量而被阻止执行时使用的处理程序。

使用执行器工厂方法创建ScheduledThreadPoolExecutor实例

建议使用Executors类提供的静态工厂方法来获取ScheduledThreadPoolExecutor,而不是直接使用上述构造方法之一创建ThreadPoolExecutor的实例。

  • newSingleThreadScheduledExecutor()–创建一个单线程执行器,该执行器可以安排命令在给定的延迟后运行或者定期执行。

  • newSingleThreadScheduledExecutor(ThreadFactory threadFactory)–创建一个单线程执行器,该执行器可以计划命令在给定的延迟后运行或者定期执行。

  • newScheduledThreadPool(int corePoolSize)–创建一个线程池,该线程池可以计划命令在给定的延迟后运行或者定期执行。

  • newScheduledThreadPool(int corePoolSize,ThreadFactory threadFactory)–创建一个线程池,该线程池可以计划命令在给定延迟后运行或者定期执行。

Java ScheduledThreadPoolExecutor中的调度方法

  • schedule(Runnable命令,长延迟,TimeUnit单位)–调度Runnable任务以在给定延迟后执行。

  • schedule(Callable <V>可调用,长延迟,TimeUnit单位)–提交一个Callable任务,以在给定延迟后执行。

  • scheduleAtFixedRate(Runnable命令,长initialDelay,长周期,TimeUnit单位)–提交一个周期性操作,该操作在给定的初始延迟后首先启用,然后在给定的周期后启用。例如,如果初始延迟为5秒,周期为2秒,则第一个任务将在5秒的延迟后执行,然后每隔2秒执行一次定期执行-initialDelay + period,initialDelay + 2 * period等上。

  • scheduleWithFixedDelay(Runnable命令,长initialDelay,长延迟,TimeUnit单位)–提交一个周期性操作,该操作在给定的初始延迟后首先启用,然后在给定的执行终止与下一次执行之间具有延迟。例如,如果初始延迟为5秒,周期为2秒,则第一个任务将在5秒钟的延迟后执行,第二个任务将排定在-(第一个任务终止+ 2秒)之后运行。

所有这些调度方法都返回类型ScheduledFuture的结果,该类型通过将Delayed接口与Future接口分开扩展来增加延迟功能。

Java ScheduledThreadPoolExecutor示例–调度Runnable

在此示例中,Executors.newSingleThreadScheduledExecutor()方法用于获取单线程执行程序以进行调度。在计划方法中,延迟设置为5秒,因此应在该延迟之后执行任务。

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.schedule(new Task(), 5, TimeUnit.SECONDS);
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        "Executed at- " + new Date());
  }
}

输出:

Time before execution started- Sat Jan 05 19:11:33 IST 2019
Executing task (thread name)- pool-1-thread-1Executed at- Sat Jan 05 19:11:38 IST 2019

Java ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法示例

本示例说明如何使用scheduleAtFixedRate()方法进行定期调度。 Executors.newScheduledThreadPool(2)方法用于创建两个线程的线程池。请注意,使用awaitTermination()方法可确保计划任务,否则shutdown()方法将不会安排新任务的发生。

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.scheduleAtFixedRate(new Task(), 5, 2, TimeUnit.SECONDS);
    try {
      // To terminate task execution after 10 seconds
      scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        " Executed at- " + new Date());
    // adding delay to keep the thread busy
    // so that another thread from pool is used
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

输出:

Time before execution started- Sat Jan 05 19:22:13 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:22:19 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:22:21 IST 2019
Executing task (thread name)- pool-1-thread-2 Executed at- Sat Jan 05 19:22:23 IST 2019

如我们所见,第一个任务计划在5秒的初始延迟后运行,之后任务计划在2秒的延迟后运行。

Java ScheduledThreadPoolExecutor的scheduleWithFixedDelay()方法示例

本示例说明如何使用scheduleWithFixedDelay()方法进行定期调度。

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.scheduleWithFixedDelay(new Task(), 5, 2, TimeUnit.SECONDS);
    try {
      // To terminate task execution after 10 seconds
      scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        " Executed at- " + new Date());
    // adding delay to keep the thread busy
    // so that another thread from pool is used
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

输出:

Time before execution started- Sat Jan 05 19:34:13 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:34:18 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:34:22 IST 2019

如我们所见,第一个任务计划在5秒的初始延迟后运行,后一个任务计划在上一个任务终止+ 2秒后运行。

使用构造函数的Java ScheduledThreadPoolExecutor示例

到目前为止显示的所有示例都使用Executors类工厂方法,这是获取ScheduledThreadPoolExecutor的推荐方法,但是我们也可以使用ScheduledThreadPoolExecutor类的构造函数。

在下一个示例中,使用构造函数之一创建ScheduledThreadPoolExecutor实例,然后安排可调用对象在延迟3秒后执行。

public class ScheduledThread {
  public static void main(String[] args) {
    // creating executor with core pool of 2 threads,  default Thread Factory
    // and handler uses abort policy
    ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(2, 
        Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    // Callable implementation
    Callable<String> c = ()->{
      System.out.println("Executed at- " + new Date());
      return "Executing task";
    };
    System.out.println("Time before execution started- " + new Date());
    // scheduling tasks with callable as param to be
    // executed after a delay of 3 Secs
    ScheduledFuture<String> sf = scheduledExecutor.schedule(c, 3, TimeUnit.SECONDS); 
    try {
      System.out.println("Value- " + sf.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

输出:

Time before execution started- Sat Jan 05 19:47:21 IST 2019
Executed at- Sat Jan 05 19:47:24 IST 2019
Value- Executing task