springboot集成常见定时任务

一、常见定时任务

原文转载

https://mp.weixin.qq.com/s/9GRxBCpeDss-llecrwo-lw

1、创建方式

  1. 使用线程创建
  2. 使用TimerTask创建
  3. 使用线程池创建
  4. 使用Quartz创建
  5. 使用springboot的@Scheduled注解

2、线程创建

public class CreatByThread {
    private static int count = 0;
    private static void timerTask(){
        Runnable runnable = new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                while (true){
                    Thread.sleep(1000);
                    count++;
                    System.err.println(count);
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }
    public static void main(String[] args) {
        timerTask();//原生写法
        new Thread(()->{//lambda表达式
            while (true){
                try {
                    Thread.sleep(1000);
                    count++;
                    System.out.println(count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

3、TimerTask创建

springboot集成常见定时任务_第1张图片

原文转载

https://blog.csdn.net/xieyuooo/article/details/8607220/
  1. 首先要明白:Timer是一个调度器,TimerTask只是一个实现了run方法的一个类(需要自己来实现)

  2. Timer和TimerTask的组合是一个单线程,如果创建多线程会使用:Executor.newScheduledThreadPool

  3. 常见的Timer类中的方法:

    • #调度一个task,经过dealy(ms)后开始调度,仅仅调度一次
          public void schedule(TimerTask task,long delay)
      
    • #调度一个task,在指定的时间点time上调度一次
          public void schedule(timertask task,Date t)
      
    • #调度一个task,在dealy(ms)后开始调度,每次调度完后,最少等待period(ms)后才开始调度
      	public void schedule(TimerTask task,long delay,long period)
      
    • #和上一个方法类似,唯一区别就是传入的第二个参数为第一次调度的时间
      	public void schedule(TimerTask task,Date firstTime,long period)
      
    • #调度一个task,在delay(ms)后开始调度,然后经过period(ms)再次调度,似乎和第三个方法类似,但不然,区别:
      #1、schedule在计算下一次执行时间的时候,是通过当前时间(在任务执行前得到)+时间片;
      #2、scheduleAtFixedRate方法是通过当前需要执行的时间(也就是现在需要执行的时间)+时间片;
      #3、schedule是运行时的实际时间,而scheduleAtFixedRate是理论时间。例如:schedule的时间片是5s,那么理论会在5101520这些时间片被调度,但如果由于某些cpu征用导致未调度,假如等到8s才被调度一次,那么schedule方法计算出来的下一次调度时间应该是13s,而不是10s,这样有可能下次越到20s后而被少调度一次或多次;而scheduleAtFixedRate就是每次理论计算出下一次需要调度的时间用以排序,若第8s被调度了,那么计算出应该是第10s,所以它距离当前时间是2s,那么在调度队列排序中,会优先调度;
      #4、scheduleAtFixedRate可以减少漏调度的情况;
      	public void scheduleAtFixedRate(TimerTask timer,long delay,long period)
      
    • #方法和上一个方法类似,唯一的区别是第一次调度的时间设置为Date,而不是当前时间的一个时间片
      	public void scheduleAtFixedRate(TimerTask timer,Date firstTime,long period)
      
public class CreatByTimerTask {
    private static int count = 0;
    private static void timerTask(){
        TimerTask timerTask = new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(1000);
                count++;
                System.err.println(count);
            }
        };
        Timer timer = new Timer();
        timer.schedule(timerTask,0,1000);//每秒调度一次
    }
    public static void main(String[] args) {
        timerTask();//原生写法
        new Timer().schedule(new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(1000);
                count++;
                System.out.println(count);
            }
        },0,1000);
    }
}

4、使用线程池创建

public class CreatByThreadPool {
    private static int count = 0;
    private static void timerTask(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                count++;
                System.err.println(count);
            }
        };
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        //第二个参数为首次执行的延迟时间,第三个参数为定时执行的间隔时间
        service.scheduleAtFixedRate(runnable,1,1, TimeUnit.SECONDS);
    }
    public static void main(String[] args) {
        timerTask();
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->{
            count++;
            System.out.println(count);
        },1,1,TimeUnit.SECONDS);
    }
}

5、使用Quartz创建

  1. maven依赖

            
            <dependency>
                <groupId>org.quartz-schedulergroupId>
                <artifactId>quartzartifactId>
                <version>2.2.1version>
            dependency>
            <dependency>
                <groupId>org.quartz-schedulergroupId>
                <artifactId>quartz-jobsartifactId>
                <version>2.2.1version>
            dependency>
    
  2. 实现了Quratz框架接口的类

    @Service
    public class QuartzServiceImpl implements Job {
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.err.println("this is a quartz method , now time:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }
    
  3. 启动类

    public class creatByQuartz {
        private static void timerTask() throws SchedulerException {
            //1、创建scheduler的工厂
            StdSchedulerFactory factory = new StdSchedulerFactory();
            //2、从工厂中获取调度器实列
            Scheduler scheduler = factory.getScheduler();
            //3、创建JobDetail
            JobDetail job = JobBuilder.newJob(QuartzServiceImpl.class)
                    //job描述
                    .withDescription("this is a quartz job")
                    //job的name和group
                    .withIdentity("quartzJob", "quartzGroup")
                    .build();
            //任务运行的时间,simpleSchedule类型触发器有效,3秒后启动任务
            long time = System.currentTimeMillis()+3*1000L;
            Date statTime = new Date(time);
            //4、创建Trigger(使用SimpleScheduleBuilder或者CronScheduleBuilder)
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withDescription("this is trigger")
                    .withIdentity("quartzTrigger", "quartzTriggerGroup")
    //                .withSchedule(SimpleScheduleBuilder.simpleSchedule())
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))//两秒执行一次,采用cron表达式
                    .startAt(statTime)//默认当前时间启动
                    .build();
            //5、注册任务和定时器
            scheduler.scheduleJob(job,trigger);
            //6、启动调度器
            scheduler.start();
        }
        public static void main(String[] args) throws SchedulerException {
            timerTask();
        }
    }
    
1、Quartz相关builder
https://blog.csdn.net/yjltx1234csdn/article/details/105846493
https://www.cnblogs.com/sunset-red/p/13794009.html

6、springboot的@Scheduled注解

  1. 在启动类上添加注解:@EnableScheduling

    @Slf4j
    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//排除连接数据库
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @EnableScheduling //开启定时任务
    public class IdempotencyApplication {
        public static void main(String[] args) throws UnknownHostException {
            ConfigurableApplicationContext applicationContext = SpringApplication.run(IdempotencyApplication.class, args);
            ConfigurableEnvironment env = applicationContext.getEnvironment();
            String ip = Inet6Address.getLocalHost().getHostAddress();
            String port = env.getProperty("server.port");
            String path = env.getProperty("server.servlet.context-path");
            log.info("----------------------------------\r\n{}","http://".concat(ip).concat(":").concat(port+path));
        }
    }
    
  2. 用注解:@Scheduled标识定时任务方法

    @Configuration
    @Component
    public class CreatByScheduled {
    //    @Scheduled(cron = "0/5 * * * * ?")//采用cron表达式执行一次定时任务
        @Scheduled(fixedRate = 5000)//指定时间5s执行一次定时任务
        public static void timerTask(){
            System.err.println("this is a timerTask:"+ LocalDate.now());
        }
    }
    
  3. 项目启动后,定时任务执行

  4. cron表达式说明

    https://blog.csdn.net/hu_dongyang/article/details/114270232
    
  5. springboot使用@Scheduled

    https://www.jianshu.com/p/c7492aeb35a1
    

你可能感兴趣的:(集成类,spring,boot,java)