Spring使用Timer实现简单的定时任务

      定时任务是一种在特定时间间隔或特定时间点自动执行的程序任务,在很多应用场景中都有广泛的应用,以下从几个方面来介绍定时任务的使用,

定时任务的应用场景

  1. 数据备份与维护
    • 描述:企业级应用通常需要定期备份重要数据,以防止数据丢失。例如,数据库备份可以在每天业务低谷期(如凌晨)进行。同时,还可以进行数据清理工作,如删除过期的日志文件、缓存数据等。
    • 示例:一个在线购物网站可能会在每天凌晨 2 点备份前一天的订单数据和用户信息,并且每月 1 号清理超过 3 个月的用户浏览历史记录。
  2. 系统监控与报告
    • 描述:为了确保系统的稳定运行,需要定期检查系统资源(如 CPU 使用率、内存占用、磁盘空间等),并生成性能报告。当系统指标超出正常范围时,还可以触发警报。
    • 示例:服务器监控工具会每 15 分钟检查一次服务器的 CPU 使用率和内存占用情况,当 CPU 使用率连续 3 次检查都超过 80% 时,发送警报通知管理员。
  3. 信息推送与更新
    • 描述:在移动应用和网站应用中,定时向用户推送通知、更新内容等。例如,新闻应用每天定时更新新闻内容,社交媒体应用定期推送用户可能感兴趣的消息。
    • 示例:一个健身应用每天晚上 8 点向用户推送第二天的健身计划提醒,以及每周推送一次健身小贴士。

 Java 中定时任务的实现方式 

1. 使用java.util.TimerTimerTask
  • 基本原理
    • Timer是一个定时器类,用于安排任务的执行。TimerTask是一个抽象类,代表一个可以被定时器执行的任务,需要继承它并实现run方法来定义任务的具体逻辑。
import java.util.Timer;
import java.util.TimerTask;

public class SimpleTimerTask {
    public static void main(String[] args) {
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("定时任务执行了");
            }
        };
        // 延迟1秒后执行任务,之后每隔2秒执行一次
        timer.schedule(task, 1000, 2000);
    }
}
  • 注意事项
    • Timer是单线程的,如果一个任务执行时间过长,会影响其他任务的按时执行。例如,若一个任务的执行时间超过了其重复执行的间隔时间,后续任务会延迟,并且可能会累积等待执行的任务。
    • Timer对象被垃圾回收时,所有未执行的任务会被取消。所以在使用过程中要确保Timer对象的生命周期符合任务执行的需求。
2. 使用ScheduledExecutorService(推荐用于复杂场景)
  • 基本原理
    • 这是 Java 并发包中的一个接口,提供了更灵活、强大的任务调度功能。可以通过Executors工厂类来创建ScheduledExecutorService的实例,然后使用它来安排任务的执行。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTask {
    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        Runnable task = () -> {
            System.out.println("定时任务执行了");
        };
        // 延迟1秒后执行任务,之后每隔2秒执行一次
        executor.scheduleAtFixedRate(task, 1000, 2000, TimeUnit.MILLISECONDS);
    }
}
  • 优势
    • 支持多线程任务调度,多个任务可以并发执行,不会因为一个任务执行时间过长而阻塞其他任务。
    • 提供了更丰富的任务调度方法,如schedule(只执行一次任务)、scheduleAtFixedRate(按照固定频率执行任务)和scheduleWithFixedDelay(在任务执行结束后,按照固定延迟执行下一次任务)等,可以根据不同的需求灵活选择。

案例 

package com.cczj.demo;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimerDemo {
    public static void main(String[] args) {
        Timer timer = new Timer();
        TimerTask backupTask = new TimerTask() {
            @Override
            public void run() {
              try {
                   System.out.println("开始定时任务...");
                    // 此处添加实际的定时任务逻辑,如连接数据库,执行备份SQL等
                } catch (Exception e) {
                    System.err.println("定时任务执行出现异常: " + e.getMessage());
                    // 可以添加更详细的日志记录逻辑,比如使用日志框架记录完整的异常堆栈信息等
                    // 也可以根据异常类型进行不同的处理,比如尝试重新执行任务等(需谨慎设计)
                       }
            }
        };
        // 安排任务在每天凌晨2点(假设时间格式转换已完成)执行
        long delay = calculateDelayToNext2AM();
        long period = 24 * 60 * 60 * 1000; // 每天执行一次
        timer.schedule(backupTask, delay, period);
    }
    private static long calculateDelayToNext2AM() {
        // 获取当前的本地日期时间
        LocalDateTime now = LocalDateTime.now();
        // 获取当前时区,确保时间计算符合所在地区的规则
        ZoneId zoneId = ZoneId.systemDefault();
        // 构建下一个凌晨2点的日期时间对象
        LocalDateTime nextTwoAM = now.toLocalDate().plusDays(1).atTime(2, 0, 0);
        if (now.toLocalTime().isAfter(LocalTime.from(LocalDateTime.of(now.toLocalDate(), nextTwoAM.toLocalTime())))) {
            // 如果当前时间已经超过了今天凌晨2点,那就往后推一天,获取下一个凌晨2点
            nextTwoAM = nextTwoAM.plusDays(1);
        }
        // 将下一个凌晨2点的本地日期时间转换为特定时区的时间戳(毫秒)
        long nextTwoAMMillis = nextTwoAM.atZone(zoneId).toInstant().toEpochMilli();
        // 获取当前时间的时间戳(毫秒)
        long currentMillis = Date.from(now.atZone(zoneId).toInstant()).getTime();
        // 计算延迟时间,即下一个凌晨2点的时间戳减去当前时间的时间戳
        return nextTwoAMMillis - currentMillis;
    }
}

整体功能概述:这段 Java 代码实现了一个简单的定时任务功能,目的是让特定的任务(在TimerTaskrun方法中定义具体逻辑,这里只是简单打印了开始执行的提示)每天凌晨 2 点定时执行一次。它通过计算当前时间到下一个凌晨 2 点的时间延迟量(delay)来安排任务首次执行的时间,然后设置固定的执行周期(period)为一天,让任务能够按照这个规律重复执行。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921909.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙NEXT开发案例:随机数生成

【引言】 本项目是一个简单的随机数生成器应用,用户可以通过设置随机数的范围和个数,并选择是否允许生成重复的随机数,来生成所需的随机数列表。生成的结果可以通过点击“复制”按钮复制到剪贴板。 【环境准备】 • 操作系统:W…

Linux 下的IO模型

一:四种IO模 1.1:阻塞式IO(最简单,最常用,效率最低) 阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。 缺省情况下(及系统默认状态)&#xf…

深度可观察性:它是什么,为什么我们需要它?

随着混合云基础设施成为现代企业的支柱,威胁形势的发展速度比以往任何时候都快。 越来越老练的攻击者、隐藏的漏洞和复杂的监管要求使 IT 和安全团队更难确保在这个复杂的环境中提供强大的保护。 2024 年 Gigamon 混合云安全调查显示,安全和 IT 领导者…

【附代码原理】偏正态分布的数据处理方法

文章目录 相关教程基本信息数学定义参数的影响Python 实现安装 scipy生成和绘制偏正态分布的数据 解释应用 右偏(即长尾在右侧)的正态分布1. 对数变换 (Log Transformation)2. 平方根变换 (Square Root Transformation)3. Box-Cox 变换注意事项 左偏&…

【STM32】MPU6050简介

文章目录 MPU6050简介MPU6050关键块带有16位ADC和信号调理的三轴MEMS陀螺仪具有16位ADC和信号调理的三轴MEMS加速度计I2C串行通信接口 MPU6050对应的数据手册:MPU6050 陀螺仪加速度计 链接: https://pan.baidu.com/s/13nwEhGvsfxx0euR2hMHsyw?pwdv2i6 提取码: v2i6…

一篇快速上手 Axios,一个基于 Promise 的网络请求库(涉及原理实现)

Axios 1. 介绍1.1 什么是 Axios?1.2 axios 和 ajax 的区别 2. 安装使用3. Axios 基本使用3.1 Axios 发送请求3.2 其他方式发送请求3.3 响应结构3.4 Request Config3.5 默认配置3.6 创建实例对象发送请求 3.7 拦截器3.8 取消请求 4. 模拟 Axios4.1 axios 对象创建过程…

趋势洞察|AI 能否带动裸金属 K8s 强势崛起?

随着容器技术的不断成熟,不少企业在开展私有化容器平台建设时,首要考虑的问题就是容器的部署环境——是采用虚拟机还是物理机运行容器?在往期“虚拟化 vs. 裸金属*”系列文章中,我们分别对比了容器部署在虚拟化平台和物理机上的架…

Unity-添加世界坐标系辅助线

如果你想在场景中更直观地显示世界坐标系,可以通过编写一个简单的脚本来实现。下面是一个基本的示例脚本,它会在场景中绘制出世界坐标系的三个轴: using UnityEngine;public class WorldAxesIndicator : MonoBehaviour {public float length…

决策树分类算法【sklearn/决策树分裂指标/鸢尾花分类实战】

决策树分类算法 1. 什么是决策树?2. DecisionTreeClassifier的使用(sklearn)2.1 算例介绍2.2 构建决策树并实现可视化 3. 决策树分裂指标3.1 信息熵(ID3)3.2 信息增益3.3 基尼指数(CART) 4. 代码…

5分钟轻松搭建Immich图片管理软件并实现公网远程传输照片

文章目录 前言1.关于Immich2.安装Docker3.本地部署Immich4.Immich体验5.安装cpolar内网穿透6.创建远程链接公网地址7.使用固定公网地址远程访问 前言 本篇文章介绍如何在本地搭建lmmich图片管理软件,并结合cpolar内网穿透实现公网远程访问到局域网内的lmmich&#…

React和Next.js的相关内容

React–前端框架 React 是一个用于构建用户界面的 JAVASCRIPT 库。 React 主要用于构建 UI,很多人认为 React 是 MVC 中的 V(视图)。 React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 …

【LeetCode热题100】队列+宽搜

这篇博客是关于队列宽搜的几道题&#xff0c;主要包括N叉树的层序遍历、二叉树的锯齿形层序遍历、二叉树最大宽度、在每个数行中找最大值。 class Solution { public:vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret;if(!root) …

丹摩征文活动|基于丹摩算力的可图(Kolors)的部署与使用

Kolors是一个以生成图像为目标的人工智能系统&#xff0c;可能采用了类似于OpenAI的DALLE、MidJourney等文本生成图像的技术。通过自然语言处理&#xff08;NLP&#xff09;和计算机视觉&#xff08;CV&#xff09;相结合&#xff0c;Kolors能够根据用户提供的文本描述生成符合…

【PTA】【数据库】【SQL命令】编程题1

数据库SQL命令测试题1 10-1 显示教工编号以02开头的教师信息 作者 冰冰 单位 广东东软学院 显示教工编号以02开头的教师信息 提示&#xff1a;请使用SELECT语句作答。 表结构: CREATE TABLE teacher ( TId CHAR(5) NOT NULL, -- 教师工号&#xff0c;主键 DId CHAR(2) …

Dockerhub镜像加速

一、背景 dockerhub由于被封锁和站点处于国外的原因&#xff0c;docker pull拉取镜像非常慢&#xff0c;有时候直接都无法拉取。严重妨碍了我们的学习进度以及日常使用。 总结了一些proxy代理的镜像站点&#xff0c;配置之后速度会有明显提升&#xff0c;大家可以参考使用。 二…

Linux: C语言解析域名

在上一篇博客 Linux: C语言发起 DNS 查询报文 中&#xff0c;自己构造 DNS 查询报文&#xff0c;发出去&#xff0c;接收响应&#xff0c;以二进制形式把响应的数据写入文件并进行分析。文章的最后留下一个悬念&#xff0c;就是写代码解析 DNS answer section 部分。本文来完成…

Tri Mode Ethernet MAC IP核详解

本文对 Vivado 的三速 MAC IP 核&#xff08;Tri Mode Ethernet MAC&#xff0c;TEMAC&#xff09;进行介绍。 在自行实现三速以太网 MAC 控制器时&#xff0c;GMII/RGMII 接口可以通过 IDDR、ODDR 原语实现&#xff0c;然而实际使用中自己实现的模块性能不是很稳定&#xff08…

CENTOS7 升级gcc版本

升级gcc版本 CentOS下升级gcc版本有两个途径&#xff0c;一个是添加其他源进行自动升级&#xff0c;一个是手动编译升级&#xff0c;这里先顺便讲下自动升级的两个办法&#xff1a; a. 添加Fedora源 在 /etc/yum.repos.d 目录中添加文件 FedoraRepo.repo &#xff0c;并输入…

VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源

VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源 由于需要在 Linux 环境下进行一些测试工作&#xff0c;于是决定使用 VMware 虚拟化软件来安装 Ubuntu 24.04 .1操作系统。考虑到测试过程中需要访问 Github &#xff0c;要使用Docker拉去镜像等外部网络资源&#xff0c;因此产…

学习日记_20241123_聚类方法(高斯混合模型)续

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…