专栏首页Java工程师成长之路定时任务实现方式对比

定时任务实现方式对比

1. 定时任务实现方式对比

1.1. Timer

  • 代码例子如下
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.now();
        String format = localDateTime.format(formatter);
        System.out.println("1:"+format);
        Timer timer = new Timer();
        for (int i = 0; i < 2; i++) {
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread name : "+ Thread.currentThread().getName());
                    LocalDateTime localDateTime = LocalDateTime.now();
                    String format = localDateTime.format(formatter);
                    System.out.println("2:"+format);
                }
            }, 3000);
        }

        localDateTime = LocalDateTime.now();
        format = localDateTime.format(formatter);
        System.out.println("3:"+format);
    }

结果

1:2019-10-14 17:35:13
3:2019-10-14 17:35:13
Thread name : Timer-0
2:2019-10-14 17:35:19
Thread name : Timer-0
2:2019-10-14 17:35:22
  • 可以看出同一个Timer的定时任务,后台就一个线程管理任务分配,遇到任务阻塞,可能导致下一个任务延迟
  • 且如果任务发生异常,系统就终止了

1.2. ScheduledExecutorService

  • 为了解决Timer的问题,ScheduledExecutorService做了改进,采用了线程池的定时任务队列,实际使用的也是最小堆排序
  • 代码如下
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static void main(String[] args) {
//        timerTest();
        print("1:");
        ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);
        for (int i = 0; i < 2; i++) {
            service.schedule(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread name : " + Thread.currentThread().getName());
                    print("2:");
                }
            }, 3, TimeUnit.SECONDS);
        }
        print("3:");
        service.shutdown();
    }

    private static void print(String s) {
        LocalDateTime localDateTime = LocalDateTime.now();
        String format = localDateTime.format(formatter);
        System.out.println(s + format);
    }

结果

1:2019-10-15 11:53:54
3:2019-10-15 11:53:54
Thread name : pool-1-thread-1
2:2019-10-15 11:54:00
Thread name : pool-1-thread-2
2:2019-10-15 11:54:00

明白它的延迟原理和Timer一样,可以知道如果我把核心线程数改成1,则效果和Timer类似

  • 结果如下,两个任务延迟3秒,前一个任务会导致后一个任务延迟
1:2019-10-15 11:57:40
3:2019-10-15 11:57:40
Thread name : pool-1-thread-1
2:2019-10-15 11:57:46
Thread name : pool-1-thread-1
2:2019-10-15 11:57:49
  • 它的优势在于可以多线程执行,一定程度上避免任务间互相影响,同时单个任务异常不影响其它任务

1.3. 时间轮(延迟消息)

  • 本质是环形数组,比如上述8个节点的时间轮,每个节点存放任务队列,比如我们需要新建5s延迟的任务,就放5的节点,新建10s延迟的任务就放2的节点,设延迟时间为n,则节点位置为n%8,同时需记下轮询圈数n/8
  • 优势:当任务数量非常多的时候采用这样环形数组加队列是个效率比较高的选择
  • 想要了解更多时间轮实现,可以参考文章下的参考博客

1.4. 分布式定时任务

  • github上也有些开源的分布式定时任务的方案,可以直接使用
  • xxl_jobelastic-job-litelight-task-scheduler,以哪个火用哪个的原则,那还是xxl_job的星星最多,另外两个已经两年没更新了

参考博客: 延迟消息之时间轮

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 达达系统架构升级经验总结

    老梁
  • 日期格式化工具方法

      以上是基于jdk8语法实现,但格式化工具还是用的SimpleDateFormat,该类通过查看它的注解,可以知道它并不是线程安全的,但是每次单独实例化它也是...

    老梁
  • 冒泡、归并和快速的算法试验

    老梁
  • 腾讯云PCDN:从P2P到万物互联服务框架

    大家好,我是腾讯云张鹏,从2014年开始一直深耕P2P技术,攻克P2P技术难题。在过去几年中,腾讯云XP2P技术已在多个产品线落地并经受了大流量阅兵直播、赛事直...

    LiveVideoStack
  • 腾讯云PCDN:从P2P到万物互联服务框架

    ? 回顾XP2P的发展历程,由为近几年兴起的直播业务节省带宽成本为出发点,经过日益发展完善,XP2P已经在底层借助STUN、端口预测、生日攻击、UPnP构建了...

    腾讯云视频
  • CVE-2020-8547 phpList 3.5.0 - Authentication Bypass 漏洞复现

    phpList是用于管理邮件列表的开源软件。它设计用于向订户列表传播信息,例如新闻通讯,新闻,广告。它用PHP编写,并使用MySQL数据库存储信息。phpLis...

    用户1631416
  • 交换机MSTP常见问题定位

    display stp brief命令中关注端口的角色和对应的状态,通过这种简要信息可以快速的检查网络中各个端口的stp情况,稳定情况下正常情况下角色状态对应关...

    网络技术联盟站
  • Python写的抢票神器成GitHub热榜第一8400星,竟然还支持候补抢票!

    这很可能是全GitHub最德高望重的购票小助手了,功能一直在更新,且现已支持Python 3.6以上版本。

    用户2769421
  • Android OpenGL ES(五)-结合相机

    上文中我们已经实现了在纹理上添加滤镜的效果。这编文章就是将OpenGl和相机结合到一起。

    deep_sadness
  • 抢票神器成GitHub热榜第一,支持候补抢票,Python跑起来 | 标星12000+

    这很可能是全GitHub最德高望重的购票小助手了,功能一直在更新,且现已支持Python 3.6以上版本。

    龙哥

扫码关注云+社区

领取腾讯云代金券