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

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

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

实现逻辑:

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

实现代码如下:

/*** 休眠实现定时任务* 来源公众号:Java技术栈*/
private static void sleepTask() {new Thread(() -> {while (true) {System.out.println("hi, 欢迎关注:Java技术栈");try {// 每隔3秒执行一次Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}).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

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

  1. Java生成二维码的两种方法

    本文介绍Java生成二维码的两种方法,这两种方法都依赖于google提供的二维码依赖包. 一种是自己写工具类,代码可以网上抄. 另一种是使用hutool第三方工具类的依赖包,不用自己抄代码. 一.自定 ...

  2. java 中lock,java中lock获取锁的四种方法

    在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...

  3. Java中的string定义的两种方法和区别

    java中的String定义的两种方法和区别 第一种:new方式 String s1 = new String("hello world"); String s2 = new St ...

  4. Java 数组转成集合List三种方法和(数组、集合List、Set相互转换)

    Java 数组转成集合List 三种方法 package com.list;import java.util.ArrayList; import java.util.Arrays; import ja ...

  5. java获取当前日期和时间的二种方法分享

    有两种方法: 方法一:用java.util.Date类来实现,并结合java.text.DateFormat类来实现时间的格式化,看下面代码: import java.util.*; import j ...

  6. Java中遍历Set集合的三种方法

    Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...

  7. php实现定时任务的两种方法

    php实现定时任务的两种方法 1.利用宝塔面板简单设置定时任务 2.在Crontab中使用URL执行脚本 1.利用宝塔面板简单设置定时任务 1,在对应的服务器上安装宝塔. 2,打开宝塔设置计划任务. ...

  8. java利用实现大数阶乘(三种方法)

    java利用实现大数阶乘(三种方法) 法一: for循环 import java.math.BigInteger; import java.util.Scanner; public class das ...

  9. Java创建并执行线程的四种方法

    Java创建并执行线程的四种方法 java里面创建线程有四种方式: 无返回: 实现Runnable接口,重写run(); 继承Thread类,重写run(); 有返回: 实现Callable接口,重写 ...

最新文章

  1. android的数据存储方式有哪几种方式,Android存储数据的5种方式
  2. 什么是ATL? (与COM的关系,及MFC与COM的关系)
  3. apache虚拟机配置步骤和修改访问端口
  4. 连接第二个 insance 到 first_local_net - 每天5分钟玩转 OpenStack(83)
  5. ELK5.3+Kafka集群配置
  6. 图像处理理论(二)——形态学、边缘检测、图像金字塔
  7. 【模拟】表达式求值(jzoj 1768)
  8. ASP.NET之JSONHelper操作
  9. CSS动画效果构成分析
  10. 编程没点为什么,生活就是十万个为什么
  11. vue 自定义指令_vue 自定义指令
  12. C#编程利器之四:委托与事件(Delegate and event) (下)
  13. 删除单链表中指针q指向的结点
  14. 德赛西威280b升级_车载导航刷机:德赛西威NAV280H固件升级
  15. 【CCF会议期刊推荐】中国计算机协会(CCF)推荐国际学术期刊/会议(软件工程/系统软件/程序设计语言)
  16. taobao.trades.sold.increment.get( 淘宝店铺订单接口,淘宝店铺订单交易数据接口,淘宝店铺订单解密接口,淘宝店铺订单解密提额接口)代码对接教程
  17. Ubuntu解决text file busy
  18. java编写桌球游戏素材小球图片_java 桌球小游戏仅一份代码
  19. 【二分答案】买礼物的艰辛
  20. 在openSUSE-Leap-15.2-DVD-x86_64下使用VLC媒体播放器

热门文章

  1. 小程序中的unionid
  2. 路由器RIP动态路由配置——思科模拟器学习
  3. Flex Builder 3代码格式化方法
  4. 【鸿蒙】鸿蒙操作系统应用开发入门级初体验
  5. 网龙网络控股有限公司公布二零一八年中期业绩
  6. 北理计算机网络实验报告,北京理工大学计算机网络实践ftp客户端实验报告.doc...
  7. springboot 整合javassist详解
  8. 百分点10周年乔迁新址 数据智能服务更上一层楼
  9. 如何在 Windows 中重新安装或修复 Internet Explorer
  10. 【web前端特效源码】使用 HTMLCSSJavaScript实现各种跳跃浮动慢跑翻转旋转坠落的魔幻文字动画效果~太上头了~/动画效果|前端开发|IT软件开发基础入门教程|网页制作|网站开发定制