Java使用线程池执行定时任务

 更新时间:2022年05月10日 09:44:29   作者:​ Java中文社群   ​  
本文介绍了Java使用线程池执行定时任务,其中ScheduledThreadPool和SingleThreadScheduledExecutor都是可以执行定时任务的,但是具体怎么执行,下面我们一起进入文章了解具体详情吧

前言:

在 Java 语言中,有两个线程池可以执行定时任务:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 可以看做是 ScheduledThreadPool 的单线程版本,它的用法和 ScheduledThreadPool 是一样的,所以本文重点来看 ScheduledThreadPool 线程池的使用。

ScheduledThreadPool 执行定时任务的方法有以下 3 个:

  • 使用 schedule 方法执行定时任务,只执行一次定时任务。
  • 使用 scheduleAtFixedRate 方法执行定时任务,执行多次定时任务。
  • 使用 scheduleWithFixedDelay 方法执行定时任务,执行多次定时任务。

接下来我们看这 3 个方法的具体使用和区别。

1.schedule

schedule 方法只能执行一次定时任务,它需要传递 3 个参数:

  • 第 1 个参数:传递一个任务,Runnable 或 Callable 对象;
  • 第 2 个参数:添加定时任务后,再过多久开始执行定时任务;
  • 第 3 个参数:时间单位,配合参数 2 一起使用。

下面我们创建一个 3 秒以后执行的定时任务:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("schedule 方法添加任务:" + LocalDateTime.now());
        threadPool.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行 schedule 方法:" + LocalDateTime.now());
            }
        }, 3, TimeUnit.SECONDS); // 3s 之后执行

        // 以下代码是给业务方法一个时间对照信息
        TimeUnit.SECONDS.sleep(10); // 休眠 10s
        System.out.println("当前时间:" + LocalDateTime.now());
    }
}

以上程序的执行结果如下图所示: 

 从上述结果中可以看出,使用 schedule 方法只能执行一次定时任务。

2.scheduleAtFixedRate

scheduleAtFixedRate 方法可以执行多次定时任务,此方法需要 4 个参数:

  • 第 1 个参数:传递一个任务,Runnable 或 Callable 对象;
  • 第 2 个参数:添加定时任务后,再过多久开始执行定时任务;
  • 第 3 个参数:定时任务执行的时间间隔;
  • 第 4 个参数:时间单位,配合参数 2 和参数 3 一起使用。

下面我们创建一个 3 秒后执行的定时任务,每个定时任务执行的时间间隔为 2 秒,

实现代码如下:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("scheduleAtFixedRate 方法添加任务:" + LocalDateTime.now());
        threadPool.scheduleAtFixedRate(new Runnable() {
                                           @Override
                                           public void run() {
                                               System.out.println("执行 scheduleAtFixedRate 方法:" + LocalDateTime.now());
                                               // 休眠 2s
                                               try {
                                                   TimeUnit.SECONDS.sleep(2);
                                               } catch (InterruptedException e) {
                                                   e.printStackTrace();
                                               }
                                           }
                                       },
                3L, // 3s 后开始执行定时任务
                2L, // 定时任务的执行间隔为 2s
                TimeUnit.SECONDS); // 描述上面两个参数的时间单位
    }
}

以上程序的执行结果如下图所示: 

 从上述结果可以看出,当任务添加成功之后,3s 后开始执行第一个定时任务,之后每隔 2s 执行一次定时任务。

3.scheduleWithFixedDelay

scheduleWithFixedDelay 方法的使用和 scheduleAtFixedRate 类似,但执行效果完全不同,这个很容易理解如果效果一样就不用创建两个方法了。 scheduleWithFixedDelay 方法是在方法执行完成之后,再隔 N 秒执行下一个定时任务,和 scheduleAtFixedRate 的固定时间执行不同,scheduleWithFixedDelay 方法的执行受定时任务执行的时长影响

比如以下代码:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("scheduleWithFixedDelay 方法添加任务:" + LocalDateTime.now());
        threadPool.scheduleWithFixedDelay(new Runnable() {
                                              @Override
                                              public void run() {
                                                  System.out.println("执行 scheduleWithFixedDelay 方法:" + LocalDateTime.now());
                                                  // 休眠 2s
                                                  try {
                                                      TimeUnit.SECONDS.sleep(2);
                                                  } catch (InterruptedException e) {
                                                      e.printStackTrace();
                                                  }
                                              }
                                          },
                3L, // 3s 后开始执行定时任务
                2L, // 定时任务执行完 2s 之后,再执行下一个定时任务
                TimeUnit.SECONDS); // 描述上面两个参数的时间单位
    }
}

以上程序的执行结果如下图所示: 

 从上述结果可以看出,定时任务在 3s 之后开始执行,以后每隔 4s 执行一次,这 4s 包含了,定时任务执行花费的 2s,加上每隔 2s 执行一次的时间间隔,也就是说 scheduleWithFixedDelay 是在任务执行完 N 秒之后,再执行下一次定时任务

总结

线程池执行定时任务的实现方法有 3 个:

  • 使用 schedule 方法执行定时任务,只执行一次定时任务。
  • 使用 scheduleAtFixedRate 方法执行定时任务,执行多次定时任务,它的执行时间间隔是固定的,不受定时任务执行时长影响(定时任务时间间隔 > 任务执行时间)。
  • 使用 scheduleWithFixedDelay 方法执行定时任务,执行多次定时任务,它是在定时任务执行完之后,再隔 N 秒开始执行下一次定时任务,它的执行时间受定时任务执行时长影响。

到此这篇关于Java使用线程池执行定时任务的文章就介绍到这了,更多相关Java行定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mybatis之@MapKey的实现

    Mybatis之@MapKey的实现

    本文介绍了Mybatis中@MapKey注解的使用场景与效果,包含使用@MapKey和不使用@MapKey注解的区别,然后通过源码解析产生各种结果的原因,具有一定的参考价值,感兴趣的可以了解一下
    2024-09-09
  • Spring Boot实现分布式任务调度的步骤

    Spring Boot实现分布式任务调度的步骤

    Spring Boot提供了一些工具和框架,可以帮助我们轻松地实现分布式任务调度,在本文中我们将介绍如何使用Spring Boot、Spring Cloud、Quartz和Redis来实现分布式任务调度,感兴趣的朋友跟随小编一起看看吧
    2023-06-06
  • IDEA使用Lombok简化POJO代码的示例

    IDEA使用Lombok简化POJO代码的示例

    今天小编就为大家分享一篇关于IDEA使用Lombok简化POJO代码的示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • MyBatis-Plus自定义通用的方法实现

    MyBatis-Plus自定义通用的方法实现

    MP自带的条件构造器虽然很强大,有时候也避免不了写稍微复杂一点业务的sql,本文主要介绍了MyBatis-Plus自定义通用的方法实现,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Java如何用时间戳重命名上传的文件

    Java如何用时间戳重命名上传的文件

    这篇文章主要介绍了Java如何用时间戳重命名上传的文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • hibernate5.2的基本配置方法(详解)

    hibernate5.2的基本配置方法(详解)

    下面小编就为大家带来一篇hibernate5.2的基本配置方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 浅谈java中字符串数组、字符串、整形之间的转换

    浅谈java中字符串数组、字符串、整形之间的转换

    这篇文章主要介绍了浅谈java中字符串数组、字符串、整形之间的转换,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • ThreadLocal使用案例_动力节点Java学院整理

    ThreadLocal使用案例_动力节点Java学院整理

    这篇文章主要介绍了ThreadLocal使用案例分析,需要的朋友可以参考下
    2017-08-08
  • 每日六道java新手入门面试题,通往自由的道路第二天

    每日六道java新手入门面试题,通往自由的道路第二天

    这篇文章主要为大家分享了最有价值的6道java面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,对hashCode方法的设计、垃圾收集的堆和代进行剖析,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Java非递归实现删除任意目录的方法

    Java非递归实现删除任意目录的方法

    这篇文章主要为大家详细介绍了Java非递归实现删除任意目录的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论