V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lufeng666
V2EX  ›  程序员

Java 定时任务求教

  •  
  •   lufeng666 · 337 天前 · 4312 次点击
    这是一个创建于 337 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 有个需求想问下各位大佬:我想用 java 技术实现被动通知。
    • 举个例子:我每周五下午 5 点都要写周报,想创建个任务,每周五下午 5 点都会给我发邮件,通知我去写周报。
    • 要求是粒度精细到每天就行,任务都是有周期的,可能每天、每周、每月、每年。
    • 我能想到的实现方式是存个 cron 表达式到 mysql 数据库,然后每天遍历一遍看是否需要触发。但是感觉很笨,有没有那种开源的三方 jar 可以引用,能快速简洁实现这样的功能的?
    58 条回复    2023-05-06 19:38:06 +08:00
    Kontinue
        1
    Kontinue  
       337 天前
    难道不是一个 @Scheduled 就完事儿了吗
    ilovey482i
        2
    ilovey482i  
       337 天前
    Quartz
    hhjswf
        3
    hhjswf  
       337 天前   ❤️ 1
    这种事情手机定个闹钟不是更简单?
    lufeng666
        4
    lufeng666  
    OP
       337 天前
    @Kontinue 每天都遍历一遍所有任务,这个方法很笨,因为大多数任务并不需要执行。数据量上来后,这个方法也特别耗性能。corn 表达式的生成与解析有没有啥好的三方库推荐的?
    grance
        5
    grance  
       337 天前   ❤️ 2
    xxl
    lission
        6
    lission  
       337 天前
    同 2 楼 Quartz
    hidemyself
        7
    hidemyself  
       337 天前
    一个定时任务就行了
    遍历每个任务看下有没有到下次执行时间,到了就执行,没到就跳过
    Bingchunmoli
        8
    Bingchunmoli  
       337 天前 via Android
    同问,如果做一个用户自定义时间的定时任务,怎么轻量一点
    yyfbbb
        9
    yyfbbb  
       337 天前
    用 github actions 执行规则,设置每周五定时执行就可以
    doyel
        10
    doyel  
       337 天前
    写个 sendmail 用 OS 的 cron 调用,一个循环日程就能完成的事情,还要跑个应用吗。。。
    linauror
        11
    linauror  
       337 天前
    感觉日历中的日程基本就可以满足你的需求(小米),可以重复每天,或者周,月,年
    crazyweeds
        12
    crazyweeds  
       337 天前
    其实自己写一个也很快,Timer 就能实现。
    轻量开源就是 Quartz ,但是也挺烦的其实。
    fengleiyidao
        13
    fengleiyidao  
       337 天前
    Quartz +1
    SmartTom
        14
    SmartTom  
       337 天前
    用分布式的 xxjob 吧
    goodidea1
        15
    goodidea1  
       337 天前
    chatgpt 会给你答案
    mmdsun
        16
    mmdsun  
       337 天前   ❤️ 1
    推荐 powerjob
    这个作者也在 v 站
    totoro52
        17
    totoro52  
       337 天前
    Quartz 还要自己写 有点麻烦, 直接上 xxl-job 吧 然后写一个发送邮件就行了 我记得里面自带, 你一句代码都不用写
    wqhui
        18
    wqhui  
       337 天前
    这么简单的操作只想 crontab 懒得写应用,或者你说个复杂点的场景?
    RightHand
        19
    RightHand  
       337 天前 via Android
    win 计划任务调用 jar ,Linux 就 cron 呗
    SilentRhythm
        20
    SilentRhythm  
       337 天前
    延时队列是否可行,创建和触发时判断下次通知的时间,不过不知道 op 数据量有多大
    Bingchunmoli
        21
    Bingchunmoli  
       337 天前 via Android
    @doyel 是想做个订阅地区天气有雨就会通知带伞的功能,如果用户可以自己输入订阅时间就有点难做,循环感觉不优雅
    lufeng666
        22
    lufeng666  
    OP
       337 天前
    @mmdsun 已 star
    issakchill
        23
    issakchill  
       337 天前
    @Scheduled 每天查一次 不会多耗性能的
    doyel
        24
    doyel  
       337 天前
    @Bingchunmoli 那就从拉取天气接口后根据根据结果给用户推吧,前提都是有监听能让你拉起提醒来,要看具体平台和场景了。
    xiongge
        25
    xiongge  
       337 天前
    你可以考虑使用 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  
       337 天前 via Android
    @doyel 做的是定时任务查询,而不是监听的
    wetalk
        27
    wetalk  
       337 天前
    简单点的用 xxl-job ,不嫌麻烦手撸时间轮
    lizhian
        28
    lizhian  
       337 天前
    手机助手不是更好吗
    CEBBCAT
        29
    CEBBCAT  
       337 天前
    系统日历不就可以吗?几乎所有的系统都带有日历功能,日历还可以云同步。我感觉可能是文化的差异,国内都忽略了日历这种软件
    chirsgod
        30
    chirsgod  
       337 天前
    PowerJob 、XXL-JOB 、Quartz 这些都可以的啊,你这个需求我感觉都用不到这种东西就能实现
    aino
        31
    aino  
       337 天前
    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  
       337 天前
    这种需求还需要( Mysql 数据库?,是不是还得考虑分布式、缓存、配置中心、服务发现、kubernetes ?
    NGXDLK
        33
    NGXDLK  
       337 天前
    1 、java 里面 @Scheduled 注解应该就能满足
    2 、不怕麻烦,搞 cron 定时任务,到点调用 java 发送邮件
    NGXDLK
        34
    NGXDLK  
       337 天前
    @PVXLL 还得考虑容灾,哈哈
    theOneMe
        35
    theOneMe  
       337 天前
    mac 里的提醒事项就行
    uasier
        36
    uasier  
       337 天前
    非 java ,青龙面板,用着很舒服
    burymme11
        37
    burymme11  
       337 天前
    @lufeng666 我大致理解你的需求了,是不是有很多个通知要推送,每个通知的调度触发点还不一样(有每周,有每月。。)?
    如果是这样,个人不推荐 xxl-job 或者 Quartz 等定时调度框架,因为如果后面数据量起来了,会构建越来越多的 job/task ,指标不治本。个人推荐走延时消息,比如 A 要每天 10 点,第一次你监听处理后,再往 topic 里丢,等第二天继续,类似,mq 也会做持久化,消息一般不会丢,读写性能肯定比 db 强
    zhaokun
        38
    zhaokun  
       336 天前
    iPhone 提醒 app 就可以实现
    nothingistrue
        39
    nothingistrue  
       336 天前
    就是个简单的按 cron 表达式发邮件,就别折腾 Java 了,写个不到 100 行的 Shell 扔给 cronb 就行了。用 Java 其实也很简单,Spring 的 @Scheduled 就够了,连 Quartz 都用不上。除非你是往现有应用里面加这个定时功能,否则不要干这种拖裤子放屁的事,没有 Linux 的话 Window 的定时计划加 bat 脚本,也能支持。
    wxw752
        40
    wxw752  
       336 天前
    @lufeng666 #4 其实定时任务扫表的方式并不笨,配合上线程池能满足很多场景了,数据量不大这么做简单高效。

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

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

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

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

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

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

    这种小事,没必要复杂化,整一堆够你写多少个周报了
    easyalarm
        58
    easyalarm  
       327 天前 via Android

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

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

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