什么是定时任务调度

定时任务调度:基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行任务。

两种java定时任务调度工具却别

Timer Quartz
小弟!功能简单,开销小 大哥!强大完善
jdk1.5 需要引入jar包
一个后台线程 后台执行线程池

Timer

有且仅有一个后台线程,对多个业务线程进行定时定频率的调度

主要构件:

Timer类中两个成员变量:

  1. TimerThread后台线程
  2. TaskQueue成员TimerTask[]

TimerThread的run方法来回调用TimerTask的run方法
总之,Timer—定时调用 TimerTask

使用

编写MyTimerTask类继承TimerTask类并重写run()方法,然后用Timer调用schedule方法来执行任务

  1. import java.util.TimerTask;
  2. public class MyTimerTask extends TimerTask{
  3. private String name;
  4. public MyTimerTask(String name){
  5. this,name = name;
  6. }
  7. @Override
  8. public void run(){
  9. System.out.println("This thread is " + this,name);
  10. }
  11. //set get
  12. }

Timer类

  1. public class MyTimer{
  2. public static void main(String[] args){
  3. Timer timer = new Timer();
  4. MyTimerTask myTimerTask = new MyTimerTask ("name1");
  5. //通过timer定时调用myTimerTask的run
  6. //2秒之后执行,此后每3秒执行一次
  7. timer.schedule(myTimerTask,2000L,3000L);
  8. }
  9. }

schedule其他用法:
1.timer.schedule(task,time);//time距1970年的毫秒数,只执行一次
2.timer.schedule(task,time,period);//time首次执行任务时间,每隔period毫秒再执行
3.timer.schedule(task,delay); //等待delay毫秒后,执行且仅执行一次task
4.timer.schedule(task,delay,period); //等待delay毫秒后,每隔period毫秒再执行

scheduleAtFixedRate的两种用法(暂时理解为同上)(有一定的并发能力) 1.timer.scheduleAtFixedRate(task,time,period);//和上面第二种方法一样
2.timer.scheduleAtFixedRate(task,delay,period);//和上面第四种方法一样

其他重要函数

TimerTask的两个函数

  • cancel() 取消当前TimerTask里的任务[在类里执行]
  • scheduledExecutionTime(),返回最近发生此任务的时间 毫秒[在主方法里执行myTimerTask.scheduledExecutionTime()]
  1. import java.util.TimerTask;
  2. public class MyTimerTask extends TimerTask{
  3. private String name;
  4. private int count = 0;
  5. public MyTimerTask(String name){
  6. this,name = name;
  7. }
  8. @Override
  9. public void run(){
  10. System.out.println("This thread is " + this,name);
  11. count++;
  12. if(count==3){
  13. //□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
  14. cancel();//取消当前任务运行!!!!!!!!!!!!!!!!
  15. //□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
  16. }
  17. }
  18. //set get
  19. }

Timer的两个函数

  • cancel() 中止所有安排的任务
  • purge() 移除队列中已取消的任务,返回溢出的任务数

总结

天生缺陷 1: 不支持并发,是同步执行的,串行执行
天生缺陷 2: Timer中执行的任务,如果有异常抛出,timer就会终止,后续的任务不会再执行,推荐使用ScheduledExecutorService。

阿里推荐的编码规约中这样写道

  1. 多线程并行处理定时任务时,Timer运行多个TimeTask
  2. ,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行
  3. ,使用ScheduledExecutorService则没有这个问题。
  4. //org.apache.commons.lang3.concurrent.BasicThreadFactory
  5. ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
  6. new BasicThreadFactory.Builder()
  7. .namingPattern("example-schedule-pool-%d").daemon(true).build());
  8. executorService.scheduleAtFixedRate(new Runnable() {
  9. @Override
  10. public void run() {
  11. //do something
  12. }
  13. },initialDelay,period, TimeUnit.HOURS);

springboot整合定时任务task只支持单点

@EnableScheduling 在配置类上使用,开启计划任务的支持(类上)
@Scheduled 来申明这是一个任务,包括cron,fixDelay,fixRate等类型(方法上,需先开启计划任务的支持)``

  1. //主要启动类
  2. @SpringBootApplication()
  3. @EnableScheduling
  4. @MapperScan("com.***.dao")
  5. public class managerToolApplication {
  6. public static void main(String[] args) {
  7. ProcessUtil.setProcessID();
  8. ApplicationContext app = SpringApplication.run(managerToolApplication.class, args);
  9. SpringUtil.setApplicationContext(app);
  10. SpringUtil.scannerBeans();
  11. }
  12. }
  13. //定时计划类
  14. @Component
  15. public class AlarmTask {
  16. /**
  17. ** @Scheduled(fixedRate = 2000)第一种:每两秒执行一次
  18. * @Scheduled(cron = "0 0/10 * * * ?")第二种 :cron表达式
  19. */
  20. @Scheduled(cron = "0 0/1 * * * ?")
  21. public void computerMonitor() {
  22. //具体逻辑
  23. }
  24. /*
  25. fixedRate 说明
  26. @Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行
  27. @Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行
  28. @Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟1秒后执行,之后按 fixedRate 的规则每6秒执行一次
  29. */
  30. }

springboot不支持年
六位 0 0/10 * ?

秒 分 时 日 月 年
4-40 4到40秒打印
0/10 从0开始,每10秒一执行
在线自动生成cron

支持分布式(整合redis,做分布式锁)

  1. /**
  2. * Redis锁(防止多点定时任务执行重复)
  3. *
  4. * @author zhaojianyu
  5. * @date 2019/7/5
  6. */
  7. public class RedisLockUtils {
  8. /**
  9. * 锁定资源 value
  10. */
  11. private static final String REDIS_LOCK_VALUE = "rtqerq342r1f341f";
  12. /**
  13. * 锁状态 true:已上锁
  14. */
  15. private static boolean status = false;
  16. /**
  17. * 上锁
  18. *
  19. * @param redisTemplate
  20. * @param time 超时时间(防止死锁)
  21. * @param timeUnit 时间单位
  22. */
  23. public static void lock(RedisTemplate<String, Object> redisTemplate, int time, TimeUnit timeUnit, String key) {
  24. if (!status) {
  25. redisTemplate.opsForValue().set(key, REDIS_LOCK_VALUE, time, timeUnit);
  26. status = true;
  27. }
  28. }
  29. /**
  30. * 获取锁
  31. *
  32. * @param redisTemplate
  33. */
  34. public static boolean getLock(RedisTemplate<String, Object> redisTemplate, String key) {
  35. status = redisTemplate.opsForValue().get(key) != null;
  36. return status;
  37. }
  38. /**
  39. * 强制拆锁
  40. *
  41. * @param redisTemplate
  42. * @param key
  43. */
  44. public static void delLock(RedisTemplate<String, Object> redisTemplate, String key) {
  45. redisTemplate.delete(key);
  46. status = false;
  47. }
  48. /**
  49. * 获取锁剩余生存时间
  50. *
  51. * @param redisTemplate
  52. * @param key
  53. * @return
  54. */
  55. public static long getLockTime(RedisTemplate<String, Object> redisTemplate, String key) {
  56. return redisTemplate.getExpire(key);
  57. }
  58. /**
  59. * 随机等待
  60. */
  61. public static void randomWait() {
  62. try {
  63. Random ra = new Random();
  64. TimeUnit.SECONDS.sleep(ra.nextInt(4));
  65. } catch (InterruptedException e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. }

springboot整合Quarz支持分布式