写点什么

不用任何框架,Java 就能实现定时任务的 3 种方法!

  • 2021 年 12 月 30 日
  • 本文字数:1954 字

    阅读完需:约 6 分钟

是的,不用任何框架,用我们朴素的 Java 编程语言就能实现定时任务。


今天,栈长就介绍 3 种实现方法,教你如何使用 JDK 实现定时任务!


1、 sleep 这也是我们最常用的 sleep 休眠大法,不只是当作休眠用,我们还可以利用它很轻松的能实现一个简单的定时任务。


实现逻辑:


新开一个线程,添加一个 for/ while 死循环,然后在死循环里面添加一个 sleep 休眠逻辑,让程序每隔 N 秒休眠再执行一次,这样就达到了一个简单定时任务的效果。


实现代码如下:


/**


  • 休眠实现定时任务

  • 来源公众号:Java 技术栈*/private static void sleepTask() {new Thread(() -> {while (true) {System.out.println("hi, 欢迎关注:Java 技术栈");

  • }).start();}这种方式比较傻瓜化了,只能按固定频率运行,不能指定具体运行的时间。


另外,上面的箭头语法,栈长使用了 JDK 8 中的 Lambda 表达式,这里就不再撰述了,Java 8 系列实战教程我都写了一堆了,不清楚的可以关注公众号:Java 技术栈,在后台回复 “java” 阅读,我都整理好了。


2、Timer 来看下 JDK 自带的 java.util.Timer 类:


JDK 1.3 就内置了 java.util.Timer 类,可以用来调度 java.util.TimerTask 任务。


几个重要的方法:


schedule:开始调度任务,提供了几个包装方法;cancle:终止任务调度,取消当前调度的所有任务,正在运行的任务不受影响;purge:从任务队列中移除所有已取消的任务;另外,java.util.TimerTask 就是实现了 Runnable 接口,具体任务逻辑则是在 run 方法里去实现。


实现代码如下:


/**


  • timer 定时任务

  • 来源公众号:Java 技术栈*/private static void timerTask() throws InterruptedException {Timer timer = new Timer();

  • TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("hi, 欢迎关注:Java 技术栈");}};

  • // 第一次任务延迟时间 long delay = 2000;

  • // 任务执行频率 long period = 3 * 1000;

  • // 开始调度 timer.schedule(timerTask, delay, period);

  • // 指定首次运行时间// timer.schedule(timerTask, DateUtils.addSeconds(new Date(), 5), period);

  • Thread.sleep(20000);

  • // 终止并移除任务 timer.cancel();timer.purge();}这种实现方式比较简单,可以指定首次执行的延迟时间、首次执行的具体日期时间,以及执行频率,能满足日常需要。


另外,需要注意的是,Timer 是线程安全的,因为背后是单线程在执行所有任务。


Timer 也会有一些缺陷:


Timer 是单线程的,假如有任务 A,B,C,任务 A 如果执行时间比较长,那么就会影响任务 B,C 的启动和执行时间,如果 B,C 执行时间也比较长,那就会相互影响;Timer 不会捕获异常,如果 A,B,C 任何一个任务在执行过程中发生异常,就会导致 TImer 整个定时任务停止工作;Timer 是基于绝对时间调度的,而不是基于相对时间,所以它对系统时间的改变非常敏感;所以,如果在使用 Timer 的过程中要注意这些缺陷,虽然可以用,但不推荐。


3、ScheduledExecutorService 因 Timer 有一些缺陷,所以不太建议使用 Timer,推荐使用 ScheduledExecutorService:


ScheduledExecutorService 即是 Timer 的替代者,JDK 1.5 并发包引入,是基于线程池设计的定时任务类:


java.util.concurrent.Executors.newScheduledThreadPool


上了线程池,每个调度任务都会分配到线程池中的某一个线程去执行,任务就是并发调度执行的,任务之间互不影响。


几个重要的调度方法:


schedule:只执行一次调度;scheduleAtFixedRate:按固定频率调度,如果执行时间过长,下一次调度会延迟,不会同时执行;scheduleWithFixedDelay:延迟调度,上一次执行完再加上延迟时间后执行;另外,可以看出,任务是支持 Runnable 和 Callable 调度的。


实现代码如下:


/**


  • 线程池定时任务

  • 来源公众号:Java 技术栈*/public static void poolTask(){ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);

  • pool.scheduleAtFixedRate(() -> {System.out.println("hi, 欢迎关注:Java 技术栈");}, 2000, 3000, TimeUnit.MILLISECONDS);}这是一个按固定频率调度的任务,创建了 10 个核心线程数,首次执行延迟 2 秒,后续每 3 秒执行一次。


这种方式简单、好用,避免了使用 Timer 带来的各种问题,推荐使用这种实现方式。


总结好了,本文栈长分享了 3 种 Java 实现定时任务的方式,也相对简单,但执行频率时间设置都太简单,只适合简单的业务,不适合实际复杂业务的需求,实际业务要考虑分布式、故障转移恢复等远要复杂的多。


最后如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163 相互学习,我们会有专业的技术答疑解惑


如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点 star: https://gitee.com/ZhongBangKeJi/crmeb_java不胜感激 !

JAVA 学习手册:https://doc.crmeb.com

技术交流论坛:https://q.crmeb.com

用户头像

还未添加个人签名 2021.11.02 加入

CRMEB就是客户关系管理+营销电商系统实现公众号端、微信小程序端、H5端、APP、PC端用户账号同步,能够快速积累客户、会员数据分析、智能转化客户、有效提高销售、会员维护、网络营销的一款企业应用

评论

发布
暂无评论
不用任何框架,Java 就能实现定时任务的 3 种方法!