Java实现定时任务

Java实现定时任务文章目录 1 使用 java util Timer2 使用 ScheduledExe 使用 SpringTask1 使用 java util Timer 这种方式的定时任务主要用到两个类 Timer 和 TimerTask 使用起来比较简单 其中 Timer 负责设定 TimerTask 的起始与间隔执行时间 TimerTask 是一个抽象类 new 的时候实现自己的 run 方法 然后将其丢给 Timer 去执行即可 代码示例 importjava time LocalDateTi

1 使用java.util.Timer

import java.time.LocalDateTime; import java.util.Timer; import java.util.TimerTask; public class Schedule { 
    public static void main(String[] args) { 
    TimerTask timerTask = new TimerTask() { 
    @Override public void run() { 
    System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); } }; // 在指定延迟0毫秒后开始,随后地执行以2000毫秒间隔执行timerTask  new Timer().schedule(timerTask, 0L, 2000L); System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); } } 

在这里插入图片描述
缺点:

  • Timer 的背后只有一个线程,不管有多少个任务,都只有一个工作线程串行执行,效率低下
  • 受限于单线程,如果第一个任务逻辑上死循环了,后续的任务一个都得不到执行
  • 依然是由于单线程,任一任务抛出异常后,整个 Timer 就会结束,后续任务全部都无法执行

2 使用ScheduledExecutorService

ScheduledExecutorService 即是 Timer 的替代者,JDK 1.5 并发包引入,是基于线程池设计的定时任务类。每个调度任务都会分配到线程池中的某一个线程去执行,任务就是并发调度执行的,任务之间互不影响

Java 5.0引入了java.util.concurrent包,其中的并发实用程序之一是ScheduledThreadPoolExecutor ,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是Timer/TimerTask组合的更通用替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类TimerTask (只需实现Runnable)。使用一个线程配置ScheduledThreadPoolExecutor使其等效于Timer 。

代码示例:

import java.time.LocalDateTime; import java.util.concurrent.*; public class Schedule { 
    public static void main(String[] args) { 
    // 创建一个ScheduledThreadPoolExecutor线程池,核心线程数为5 ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(5); // 创建Runnable打印当前线程和当前时间 Runnable r = () -> System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); / * schedule:只执行一次调度 * scheduleAtFixedRate:一开始就计算间隔时间,如果任务超过间隔时间,那么就直接开始下一个任务 * scheduleWithFixedDelay:任务无论执行多久,都要等待上一轮任务完成之后再间隔指定时间,然后才开始下一个任务 */ // 在指定1秒延迟后执行r,之后每两秒执行一次 scheduledExecutorService.scheduleAtFixedRate(r, 1, 2, TimeUnit.SECONDS); } } 

在这里插入图片描述

3 使用Spring Task

Spring Task 底层是基于 JDK 的 ScheduledThreadPoolExecutor 线程池来实现的。直接通过Spring 提供的 @Scheduled 注解即可定义定时任务,非常方便。

以Spring Boot来作为示例,步骤为

  1. 在启动类所在包下创建Schedule 类(在没有配置@ComponentScan的情况下,Spring Boot只会默认扫描启动类所在包的spring组件)
  2. 在该类上添加@Component和@EnableScheduling注解
  3. 在方法上添加@Scheduled注解,该注解主要参数如下
String cron() default ""; // 支持cron表达式 long fixedDelay() default -1; // 在最后一次调用结束和下一次调用开始之间的时间间隔,以毫秒为单位 String fixedDelayString() default ""; // 同上,类似ScheduledExecutorService的scheduleWithFixedDelay long fixedRate() default -1; // 在调用之前的时间间隔,以毫秒为单位 String fixedRateString() default ""; // 同上,类似ScheduledExecutorService的scheduleAtFixedRate long initialDelay() default -1; // 在第一次执行fixedRate()或fixedDelay()任务之前要延迟的毫秒数 String initialDelayString() default ""; // 同上 

代码示例:

import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component @EnableScheduling public class Schedule { 
    @Scheduled(fixedRate = 2000L) public void task() { 
    System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); } } 

在这里插入图片描述

  • 优点: 简单,轻量,支持 Cron 表达式
  • 缺点 :默认只支持单机,是单线程的,并且提供的功能比较单一

可以通过@EnableAsync和 @Async开启多线程

import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component @EnableAsync // 开启异步多线程 @EnableScheduling public class Schedule { 
    @Async @Scheduled(fixedRate = 2000L) public void task() { 
    System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); } } 

在这里插入图片描述

使用@EnableAsync注解后,默认情况下,Spring将搜索关联的线程池定义:上下文中的唯一org.springframework.core.task.TaskExecutor
的bean,或者名为“taskExecutor”的java.util.concurrent.Executor
的bean。如果两者都无法解析,则将使用org.springframework.core.task.SimpleAsyncTaskExecutor来处理异步方法调用。




在这里插入图片描述

TaskExecutor实现为每个任务启动一个新线程,异步执行它。 支持通过“concurrencyLimit”bean 属性限制并发线程。默认情况下,并发线程数是无限的,所以使用默认的线程池有导致内存溢出的风险

注意:刚才的运行结果看起来是线程复用的,而实际上此实现不重用线程应尽量实现一个线程池TaskExecutor ,特别是用于执行大量短期任务。不要使用默认的SimpleAsyncTaskExecutor。

import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.concurrent.Executor; @Component @EnableAsync @EnableScheduling public class Schedule { 
    @Async @Scheduled(fixedRate = 2000L) public void task() { 
    System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now()); } @Bean("taskExecutor") public Executor taskExecutor() { 
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(10); taskExecutor.setMaxPoolSize(50); taskExecutor.setQueueCapacity(200); taskExecutor.setKeepAliveSeconds(60); taskExecutor.setThreadNamePrefix("自定义-"); taskExecutor.setAwaitTerminationSeconds(60); return taskExecutor; } } 

在这里插入图片描述

上面提到的一些定时任务的解决方案都是在单机下执行的,适用于比较简单的定时任务场景比如每天凌晨备份一次数据。如果我们需要一些高级特性比如支持任务在分布式场景下的分片和高可用的话,我们就需要用到分布式任务调度框架了,比如Quartz、Elastic-Job、XXL-JOB、PowerJob,本文就不再详细进行介绍了,感兴趣的可以自行查阅相关资料。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224935.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午10:48
下一篇 2026年3月17日 上午10:48


相关推荐

  • Modbus CRC校验算法

    uint16_tcrc_reflect(uint16_tdata,int32_tlen){uint16_tret=data&0x01;for(int32_ti=1;i<len;i++){data>>=1;ret=(ret<<1)|(data&am…

    2022年4月7日
    60
  • dirsearch安装教程「建议收藏」

    dirsearch安装教程「建议收藏」dirsearch安装教程dirsearch是一个用python开发的网站目录扫描工具github下载地址笔者安装在windows上下载的是zip包因为需要用到python直接解压到安装python环境的位置打开cmd进入dirsearch目录后,输入命令进行安装pythonsetup.py安装成功后就可以直接使用了pythondirsearch.py-uip命令详解dirsearch-h到这里就结束了…

    2022年10月5日
    4
  • 奉劝那些刚参加工作的学弟学妹们:这些计算机与操作系统基础知识越早知道越好!万字长文太顶了!!(建议收藏)

    奉劝那些刚参加工作的学弟学妹们:这些计算机与操作系统基础知识越早知道越好!万字长文太顶了!!(建议收藏)2.5万字54张图带你彻底学透计算机与操作系统基础,文章有点长,建议收藏后阅读!!

    2022年6月22日
    44
  • 布隆过滤器原理简介视频_布隆过滤器误判怎么办

    布隆过滤器原理简介视频_布隆过滤器误判怎么办目录1.布隆过滤器简介2.布隆过滤器的实现思路3.布隆过滤器的公式4.实际应用场景1.布隆过滤器简介布隆过滤器(BloomFilter)是由一个很长的bit数组和一系列哈希函数组成的。本质上是一种数据结构,比较巧妙的概率型数据结构。它的特点是高效地插入和查询,并且根据查询结果可以知道某样东西一定不存在或者可能存在。相比于传统的List、Set、Map等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的,同时布隆过滤器还有一个缺陷就是数据只..

    2022年10月7日
    4
  • leetcode-221. 最大正方形(动态规划)「建议收藏」

    leetcode-221. 最大正方形(动态规划)「建议收藏」在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。示例 1:输入:matrix = [[“1″,”0″,”1″,”0″,”0”],[“1″,”0″,”1″,”1″,”1”],[“1″,”1″,”1″,”1″,”1”],[“1″,”0″,”0″,”1″,”0”]]输出:4示例 2:输入:matrix = [[“0″,”1”],[“1″,”0”]]输出:1示例 3:输入:matrix = [[“0”]]输出:0 提示:m == ma

    2022年8月9日
    7
  • 博客搬家

    博客搬家我的另一个博客http://www.cnblogs.com/dingxiaowei欢迎光临,共同学习!我的新浪微博http://blog.sina.com.cn/dingxiaowei2013转载于:https://www.cnblogs.com/java20130723/archive/2013/01/04/3211485.html…

    2022年5月29日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号