Java 实现定时任务的三种方法
是的,不用任何框架,用我们朴素的Java编程语言就能实现定时任务。
今天,栈长就介绍3种实现方法,教你如何使用JDK实现定时任务!
1、sleep
这也是我们最常用的sleep休眠大法,不只是当作休眠用,我们还可以利用它很轻松的能实现一个简单的定时任务。
实现逻辑:
新开一个线程,添加一个for/while死循环,然后在死循环里面添加一个sleep休眠逻辑,让程序每隔N秒休眠再执行一次,这样就达到了一个简单定时任务的效果。
实现代码如下:
privatestaticvoidsleepTask(){ newThread(()->{ while(true){ System.out.println("hi,欢迎关注:Java技术栈"); try{ //每隔3秒执行一次 Thread.sleep(3000); }catch(InterruptedExceptione){ e.printStackTrace(); } } }).start(); }
这种方式比较傻瓜化了,只能按固定频率运行,不能指定具体运行的时间。
另外,上面的箭头语法,栈长使用了JDK8中的Lambda表达式,这里就不再撰述了,Java8系列实战教程我都写了一堆了,不清楚的可以关注公众号:Java技术栈,在后台回复"java"阅读,我都整理好了。
2、Timer
来看下JDK自带的java.util.Timer类:
JDK1.3就内置了java.util.Timer类,可以用来调度java.util.TimerTask任务。
几个重要的方法:
- schedule:开始调度任务,提供了几个包装方法;
- cancle:终止任务调度,取消当前调度的所有任务,正在运行的任务不受影响;
- purge:从任务队列中移除所有已取消的任务;
另外,java.util.TimerTask就是实现了Runnable接口,具体任务逻辑则是在run方法里去实现。
实现代码如下:
privatestaticvoidtimerTask()throwsInterruptedException{ Timertimer=newTimer(); TimerTasktimerTask=newTimerTask(){ @Override publicvoidrun(){ System.out.println("hi,欢迎关注:Java技术栈"); } }; //第一次任务延迟时间 longdelay=2000; //任务执行频率 longperiod=3*1000; //开始调度 timer.schedule(timerTask,delay,period); //指定首次运行时间 //timer.schedule(timerTask,DateUtils.addSeconds(newDate(),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的替代者,JDK1.5并发包引入,是基于线程池设计的定时任务类:
java.util.concurrent.Executors.newScheduledThreadPool
上了线程池,每个调度任务都会分配到线程池中的某一个线程去执行,任务就是并发调度执行的,任务之间互不影响。
几个重要的调度方法:
- schedule:只执行一次调度;
- scheduleAtFixedRate:按固定频率调度,如果执行时间过长,下一次调度会延迟,不会同时执行;
- scheduleWithFixedDelay:延迟调度,上一次执行完再加上延迟时间后执行;
另外,可以看出,任务是支持Runnable和Callable调度的。
实现代码如下:
publicstaticvoidpoolTask(){ ScheduledExecutorServicepool=Executors.newScheduledThreadPool(10); pool.scheduleAtFixedRate(()->{ System.out.println("hi,欢迎关注:Java技术栈"); },2000,3000,TimeUnit.MILLISECONDS); }
这是一个按固定频率调度的任务,创建了10个核心线程数,首次执行延迟2秒,后续每3秒执行一次。
这种方式简单、好用,避免了使用Timer带来的各种问题,推荐使用这种实现方式。
总结
好了,本文栈长分享了3种Java实现定时任务的方式,也相对简单,但执行频率时间设置都太简单,只适合简单的业务,不适合实际复杂业务的需求,实际业务要考虑分布式、故障转移恢复等远要复杂的多。
本文仅给大家一个参考吧,在不用框架的前提下也能实现定时任务,在小而美的场景,还是很香的。
最后,Java系列教程还会继续更新,关注Java技术栈公众号第一时间推送,还可以在公众号菜单中获取历史Java教程,都是干货。
本节教程所有实战源码已上传到这个仓库:
https://github.com/javastacks/javastack
最后,觉得我的文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长需要你的鼓励。
以上就是Java实现定时任务的三种方法的详细内容,更多关于Java实现定时任务的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。