V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lufeng666
V2EX  ›  程序员

Java 定时任务求教

  •  
  •   lufeng666 · 2023-04-27 14:43:02 +08:00 · 4921 次点击
    这是一个创建于 609 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 有个需求想问下各位大佬:我想用 java 技术实现被动通知。
    • 举个例子:我每周五下午 5 点都要写周报,想创建个任务,每周五下午 5 点都会给我发邮件,通知我去写周报。
    • 要求是粒度精细到每天就行,任务都是有周期的,可能每天、每周、每月、每年。
    • 我能想到的实现方式是存个 cron 表达式到 mysql 数据库,然后每天遍历一遍看是否需要触发。但是感觉很笨,有没有那种开源的三方 jar 可以引用,能快速简洁实现这样的功能的?
    58 条回复    2023-05-06 19:38:06 +08:00
    Kontinue
        1
    Kontinue  
       2023-04-27 14:45:09 +08:00
    难道不是一个 @Scheduled 就完事儿了吗
    ilovey482i
        2
    ilovey482i  
       2023-04-27 14:46:12 +08:00
    Quartz
    hhjswf
        3
    hhjswf  
       2023-04-27 14:48:03 +08:00   ❤️ 1
    这种事情手机定个闹钟不是更简单?
    lufeng666
        4
    lufeng666  
    OP
       2023-04-27 14:48:40 +08:00
    @Kontinue 每天都遍历一遍所有任务,这个方法很笨,因为大多数任务并不需要执行。数据量上来后,这个方法也特别耗性能。corn 表达式的生成与解析有没有啥好的三方库推荐的?
    grance
        5
    grance  
       2023-04-27 14:49:58 +08:00   ❤️ 2
    xxl
    lission
        6
    lission  
       2023-04-27 14:52:14 +08:00
    同 2 楼 Quartz
    hidemyself
        7
    hidemyself  
       2023-04-27 14:53:15 +08:00
    一个定时任务就行了
    遍历每个任务看下有没有到下次执行时间,到了就执行,没到就跳过
    Bingchunmoli
        8
    Bingchunmoli  
       2023-04-27 14:56:32 +08:00 via Android
    同问,如果做一个用户自定义时间的定时任务,怎么轻量一点
    yyfbbb
        9
    yyfbbb  
       2023-04-27 14:56:38 +08:00
    用 github actions 执行规则,设置每周五定时执行就可以
    doyel
        10
    doyel  
       2023-04-27 15:03:25 +08:00
    写个 sendmail 用 OS 的 cron 调用,一个循环日程就能完成的事情,还要跑个应用吗。。。
    linauror
        11
    linauror  
       2023-04-27 15:03:34 +08:00
    感觉日历中的日程基本就可以满足你的需求(小米),可以重复每天,或者周,月,年
    crazyweeds
        12
    crazyweeds  
       2023-04-27 15:04:39 +08:00
    其实自己写一个也很快,Timer 就能实现。
    轻量开源就是 Quartz ,但是也挺烦的其实。
    fengleiyidao
        13
    fengleiyidao  
       2023-04-27 15:08:13 +08:00
    Quartz +1
    SmartTom
        14
    SmartTom  
       2023-04-27 15:16:55 +08:00
    用分布式的 xxjob 吧
    goodidea1
        15
    goodidea1  
       2023-04-27 15:24:19 +08:00
    chatgpt 会给你答案
    mmdsun
        16
    mmdsun  
       2023-04-27 15:25:11 +08:00   ❤️ 1
    推荐 powerjob
    这个作者也在 v 站
    totoro52
        17
    totoro52  
       2023-04-27 15:27:54 +08:00
    Quartz 还要自己写 有点麻烦, 直接上 xxl-job 吧 然后写一个发送邮件就行了 我记得里面自带, 你一句代码都不用写
    wqhui
        18
    wqhui  
       2023-04-27 15:32:12 +08:00
    这么简单的操作只想 crontab 懒得写应用,或者你说个复杂点的场景?
    RightHand
        19
    RightHand  
       2023-04-27 15:36:51 +08:00 via Android
    win 计划任务调用 jar ,Linux 就 cron 呗
    SilentRhythm
        20
    SilentRhythm  
       2023-04-27 15:44:38 +08:00
    延时队列是否可行,创建和触发时判断下次通知的时间,不过不知道 op 数据量有多大
    Bingchunmoli
        21
    Bingchunmoli  
       2023-04-27 15:52:01 +08:00 via Android
    @doyel 是想做个订阅地区天气有雨就会通知带伞的功能,如果用户可以自己输入订阅时间就有点难做,循环感觉不优雅
    lufeng666
        22
    lufeng666  
    OP
       2023-04-27 15:54:32 +08:00
    @mmdsun 已 star
    issakchill
        23
    issakchill  
       2023-04-27 16:10:23 +08:00
    @Scheduled 每天查一次 不会多耗性能的
    doyel
        24
    doyel  
       2023-04-27 16:13:32 +08:00
    @Bingchunmoli 那就从拉取天气接口后根据根据结果给用户推吧,前提都是有监听能让你拉起提醒来,要看具体平台和场景了。
    xiongge
        25
    xiongge  
       2023-04-27 16:18:58 +08:00
    你可以考虑使用 Quartz Scheduler 这个开源的 Java 库来实现你的需求。它是一个功能强大的任务调度框架,支持多种任务周期(每天、每周、每月、每年等),可以非常方便地设置任务的触发时间和频率,并且支持任务的持久化存储。

    在你的应用中引入 Quartz Scheduler 库后,你可以通过编写一个 Job 类来定义你的任务逻辑,然后通过创建一个 Trigger 对象来设置任务的触发时间和频率。你还可以将任务的配置信息存储到数据库中,并且在应用启动时从数据库中读取配置信息来动态创建任务。

    以下是一个使用 Quartz Scheduler 实现定时发送邮件的示例代码:

    java
    Copy code
    // 定义一个 Job 类来发送邮件
    public class SendEmailJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
    // 在这里编写发送邮件的逻辑
    }
    }

    // 创建一个 Trigger 对象来设置任务的触发时间和频率
    Trigger trigger = TriggerBuilder.newTrigger()
    .withIdentity("sendEmailTrigger", "email")
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 17 ? * FRI")) // 每周五下午 5 点触发
    .build();

    // 创建一个 SchedulerFactory 对象并启动 Scheduler
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler scheduler = sf.getScheduler();
    scheduler.start();

    // 注册 Job 和 Trigger
    JobDetail job = JobBuilder.newJob(SendEmailJob.class)
    .withIdentity("sendEmailJob", "email")
    .build();
    scheduler.scheduleJob(job, trigger);
    在上面的代码中,我们定义了一个 SendEmailJob 类来发送邮件,然后创建了一个 Trigger 对象来设置任务的触发时间和频率,最后将 Job 和 Trigger 注册到 Scheduler 中。在 Scheduler 启动后,当触发时间到达时,Quartz Scheduler 就会自动执行 SendEmailJob 中定义的发送邮件逻辑。

    希望这个示例能够帮助你实现你的需求。
    Bingchunmoli
        26
    Bingchunmoli  
       2023-04-27 16:21:15 +08:00 via Android
    @doyel 做的是定时任务查询,而不是监听的
    wetalk
        27
    wetalk  
       2023-04-27 16:23:02 +08:00
    简单点的用 xxl-job ,不嫌麻烦手撸时间轮
    lizhian
        28
    lizhian  
       2023-04-27 16:24:37 +08:00
    手机助手不是更好吗
    CEBBCAT
        29
    CEBBCAT  
       2023-04-27 16:59:05 +08:00
    系统日历不就可以吗?几乎所有的系统都带有日历功能,日历还可以云同步。我感觉可能是文化的差异,国内都忽略了日历这种软件
    chirsgod
        30
    chirsgod  
       2023-04-27 16:59:55 +08:00
    PowerJob 、XXL-JOB 、Quartz 这些都可以的啊,你这个需求我感觉都用不到这种东西就能实现
    aino
        31
    aino  
       2023-04-27 17:09:34 +08:00
    Cron 表达式是一种用于指定定时任务执行时间的语法格式。它由 6 个字段组成,分别表示秒、分、时、日、月、周几。每个字段可以是一个数值、一组数值、一个范围、一个通配符或一些组合。

    Cron 表达式的格式为:秒 分 时 日 月 周几

    下面是每个字段可以包含的值:

    秒:0~59
    分:0~59
    时:0~23
    日:1~31
    月:1~12
    周几:0~6 ( 0 表示周日)
    除了上述的数值外,还可以使用通配符*表示任意值,使用逗号,表示多个值,使用连字符-表示一个范围,使用斜杠 /表示间隔时间。

    例如,下面的 Cron 表达式表示每天的上午 10 点执行一次任务:

    0 0 10 * * ?

    又如,下面的 Cron 表达式表示每周五晚上 10 点到 11 点之间每隔 5 分钟执行一次任务:

    0 */5 22-23 ? * FRI
    PVXLL
        32
    PVXLL  
       2023-04-27 17:18:04 +08:00
    这种需求还需要( Mysql 数据库?,是不是还得考虑分布式、缓存、配置中心、服务发现、kubernetes ?
    NGXDLK
        33
    NGXDLK  
       2023-04-27 17:20:33 +08:00
    1 、java 里面 @Scheduled 注解应该就能满足
    2 、不怕麻烦,搞 cron 定时任务,到点调用 java 发送邮件
    NGXDLK
        34
    NGXDLK  
       2023-04-27 17:23:05 +08:00
    @PVXLL 还得考虑容灾,哈哈
    theOneMe
        35
    theOneMe  
       2023-04-27 17:28:09 +08:00
    mac 里的提醒事项就行
    uasier
        36
    uasier  
       2023-04-27 17:31:37 +08:00
    非 java ,青龙面板,用着很舒服
    burymme11
        37
    burymme11  
       2023-04-27 17:40:33 +08:00
    @lufeng666 我大致理解你的需求了,是不是有很多个通知要推送,每个通知的调度触发点还不一样(有每周,有每月。。)?
    如果是这样,个人不推荐 xxl-job 或者 Quartz 等定时调度框架,因为如果后面数据量起来了,会构建越来越多的 job/task ,指标不治本。个人推荐走延时消息,比如 A 要每天 10 点,第一次你监听处理后,再往 topic 里丢,等第二天继续,类似,mq 也会做持久化,消息一般不会丢,读写性能肯定比 db 强
    zhaokun
        38
    zhaokun  
       2023-04-27 17:44:09 +08:00
    iPhone 提醒 app 就可以实现
    nothingistrue
        39
    nothingistrue  
       2023-04-27 17:45:57 +08:00
    就是个简单的按 cron 表达式发邮件,就别折腾 Java 了,写个不到 100 行的 Shell 扔给 cronb 就行了。用 Java 其实也很简单,Spring 的 @Scheduled 就够了,连 Quartz 都用不上。除非你是往现有应用里面加这个定时功能,否则不要干这种拖裤子放屁的事,没有 Linux 的话 Window 的定时计划加 bat 脚本,也能支持。
    wxw752
        40
    wxw752  
       2023-04-27 17:51:40 +08:00
    @lufeng666 #4 其实定时任务扫表的方式并不笨,配合上线程池能满足很多场景了,数据量不大这么做简单高效。

    如果真是有上百万要发的邮件,那时候我相信你会选择 mq
    sadfQED2
        41
    sadfQED2  
       2023-04-27 17:59:44 +08:00 via Android
    while(True){
    sleep(1000)
    if(time==XXX){发邮件}
    }
    direction
        42
    direction  
       2023-04-27 18:33:38 +08:00
    xxl-job
    oneisall8955
        43
    oneisall8955  
       2023-04-27 18:51:14 +08:00 via Android
    腾讯轻联,原腾讯 hiflow ,2023 年 9 月 22 日前升级个版每月 3000 个任务,免费版 1000 个任务。感觉还行
    zhady009
        45
    zhady009  
       2023-04-27 21:33:07 +08:00
    如果就如你描述的那样根本没必要引用什么库

    如果有更复杂的要求和场景才可能需要
    mundane
        46
    mundane  
       2023-04-27 21:58:02 +08:00
    如果 cron 表达式不用经常变的话,@Scheduled 注解就行了,多个任务就用多个 @Scheduled
    lucaslee
        47
    lucaslee  
       2023-04-27 22:20:24 +08:00
    如果你想练手写代码,那二楼已经有答案了。如果就是为了完成你的任务,那么找个现成的手机 app 吧,按照你的描述,todo 类的就足够用了,我认为是成本最低的。
    carytseng
        48
    carytseng  
       2023-04-27 22:35:28 +08:00
    我司的钉钉每天下班前会提醒写周报
    009694
        49
    009694  
       2023-04-28 00:16:47 +08:00 via iPhone
    crontab+python 1 分钟写完的需求 愣是被你描述成需要先评审再立项的大项目了
    Ericcccccccc
        50
    Ericcccccccc  
       2023-04-28 00:46:22 +08:00
    定时任务本质就是轮训, 你想的方法是正确的

    而实际上实现一个定时任务系统, 可以配置各种任务就是用数据库实现的, 先看哪些任务要执行, 然后写进数据库里, 然后轮训, 到了要执行的时候就拿出来执行
    tedzhou1221
        51
    tedzhou1221  
       2023-04-28 09:33:29 +08:00
    “每天遍历一遍看是否需要触发” 也没多笨。主要是简单。

    我有个想法。(只是想法) 参考多级时间轮的实现方式。或 Rocket MQ 的延时列队 级别

    年级别、月级别、天级别。年级别,一年只会遍历一次,月级别一个月遍历一次。

    反正就是复杂设计了。如果没多少数据里,每天全遍历也不会有什么问题吧。
    hongchends1
        52
    hongchends1  
       2023-04-28 09:59:03 +08:00
    你可以搞个 iOS 上的自动化 每周五触发
    miaotaizi
        53
    miaotaizi  
       2023-04-28 10:06:05 +08:00
    定时任务去读取配置的提醒(将来要发生的), 往延迟队列里面推 是不是就解决了
    fifa899
        54
    fifa899  
       2023-04-28 11:21:57 +08:00
    日级别的设置个每日任务.每天晚上遍历任务表.发送每日任务延时消息到 MQ 延迟队列.
    我们线上几百个用户就是这么搞的.不可能做几百个定时线程挂在服务器里
    MonkeyJon
        55
    MonkeyJon  
       2023-04-28 13:43:05 +08:00
    xxlJob 方便简洁
    howfree
        56
    howfree  
       2023-04-28 16:22:15 +08:00
    xxljob
    season8
        57
    season8  
       2023-04-28 17:28:47 +08:00
    最简单是闹钟、日程提醒,或者相关微信公众号提醒
    都 cron 了,直接一个 shell 脚本呗
    都就 java 了,用 spring 的定时任务也行啊,多个任务怕延迟可以搞个线程池
    好多任务需要管理,用 xxl

    这种小事,没必要复杂化,整一堆够你写多少个周报了
    easyalarm
        58
    easyalarm  
       2023-05-06 19:38:06 +08:00 via Android

    https://drive.google.com/drive/mobile/folders/1M5YBI9zBE6-dV6o0sQo-8wNAgq-hPcYV
    下载一个 apk

    然后把这两行贴进去就行了

    提醒:再不写写周班就卷铺盖回家
    每周:5 时间:15:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1041 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 22:37 · PVG 06:37 · LAX 14:37 · JFK 17:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.