zoukankan      html  css  js  c++  java
  • 定时任务

    开启定时任务功能

    package com.huang.pims;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @SpringBootApplication
    @ComponentScan(basePackages = {"com.huang.pims.*"})
    @EnableCaching
    // 开启定时任务功能 @EnableScheduling
    public class PimsApplication { public static void main(String[] args) { SpringApplication.run(PimsApplication.class, args); } }

    创建定时任务的示例

    package com.huang.pims.schedule.tasks;
    
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @Service
    public class ScheduledTaskDemo01 {
    
        /**
         * 每分钟内秒数为3的倍数的时间点皆可以执行任务
         * 如果因执行上一个任务,而错过了一个多个时间点,则需等待至最近的一个时间点方可以继续执行
         * 例如,3,6,9,12,15,18,21等等,这些都是可以执行任务的时间点
         * 如果在时间点6执行了一个耗时7s的任务,那么时间点9和时间点12就无法执行任务,必须等到时间点15,才可以执行下次任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 那么,
         * while(actuallyTime % 3 == 0 && actuallyTime <= nowTime + exeTime) {
         *      actuallyTime += 3;
         * }
         *
         */
        @Scheduled(cron = "0/3 * * * * *")
        public void cronTask() {
            System.out.println("定时任务:每过3s执行一次任务");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.cronTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date()));
        }
    
    
        /**
         * 周期性延迟执行任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 那么,actuallyTime >= nowTime + exeTime + fixedDelay;
         */
        @Scheduled(fixedDelay = 2000)
        public void delayTask() {
            System.out.println("定时任务:执行完一次任务后,先延迟2秒再执行下一次任务");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date()));
        }
    
        /**
         * 周期性执行任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 如果 exeTime >= fixedRate ,那么,actuallyTime >= nowTime + exeTime;
         * 如果 exeTime < fixedRate , 那么,actuallyTime >= nowTime + fixedRate;
         */
        @Scheduled(fixedRate = 2000)
        public void periodTask() {
            System.out.println("定时任务:每2秒执行一次");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 结束时间:" + sdf.format(new Date()));
        }
    
    }

      如果想看到效果,直接启动项目即可。从结果可以看出,这些任务都是由同一条线程串行调度的。如果任务较少,还可以接受,但是如果任务很多,任务也很耗时,那就不适合了。这时可以使用@EnableAsync注解来开启对异步事件的支持,@Async来注解定时任务类或方法。这样可以使得,每次执行的任务都将由一条新的线程来执行。如此,可以使用线程池的技术来进一步优化,毕竟无限的创建、销毁线程很消耗性能。

    定时任务的配置优化

    配置定时任务的线程池

    package com.huang.pims;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    @SpringBootApplication
    @ComponentScan(basePackages = {"com.huang.pims.*"})
    @EnableCaching
    @EnableScheduling // 开启定时任务
    @EnableAsync // 开启异步支持
    public class PimsApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(PimsApplication.class, args);
        }
    
        @Bean
        public ThreadPoolTaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(10);// 核心线程数
            taskExecutor.setMaxPoolSize(15);// 最大线程数
            taskExecutor.initialize();
            return taskExecutor;
        }
    
    }

    使用了@Async来注解定时任务类

    package com.huang.pims.schedule.tasks;
    
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @Service
    @Async
    public class ScheduledTaskDemo01 {
    
        /**
         * 每分钟内秒数为3的倍数的时间点皆可以执行任务
         * 如果因执行上一个任务,而错过了一个多个时间点,则需等待至最近的一个时间点方可以继续执行
         * 例如,3,6,9,12,15,18,21等等,这些都是可以执行任务的时间点
         * 如果在时间点6执行了一个耗时7s的任务,那么时间点9和时间点12就无法执行任务,必须等到时间点15,才可以执行下次任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 那么,
         * while(actuallyTime % 3 == 0 && actuallyTime <= nowTime + exeTime) {
         *      actuallyTime += 3;
         * }
         *
         */
        @Scheduled(cron = "0/3 * * * * *")
        public void cronTask() {
            System.out.println("定时任务:每过3s执行一次任务");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.cronTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date()));
        }
    
    
        /**
         * 周期性延迟执行任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 那么,actuallyTime >= nowTime + exeTime + fixedDelay;
         */
        @Scheduled(fixedDelay = 2000)
        public void delayTask() {
            System.out.println("定时任务:执行完一次任务后,先延迟2秒再执行下一次任务");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date()));
        }
    
        /**
         * 周期性执行任务
         *
         * 假设:
         *      执行一次任务需要消耗的时间为 exeTime
         *      执行此次任务的开始时间是 nowTime
         *      执行下一次任务的实际时间是 actuallyTime
         * 如果 exeTime >= fixedRate ,那么,actuallyTime >= nowTime + exeTime;
         * 如果 exeTime < fixedRate , 那么,actuallyTime >= nowTime + fixedRate;
         */
        @Scheduled(fixedRate = 2000)
        public void periodTask() {
            System.out.println("定时任务:每2秒执行一次");
            System.out.println("当前线程:"+Thread.currentThread().getName());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 开始时间:" + sdf.format(new Date()));
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {}
            System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 结束时间:" + sdf.format(new Date()));
        }
    
    }

      开启项目,即可看到定时任务的效果。

      

  • 相关阅读:
    什么是HTTPS协议
    思维:从互联网到区块链
    BFT-SMaRt:用Netty做客户端的可靠信道
    BFT-SMaRt:用Java做节点间的可靠信道
    共识网络BFT-SMaRt:理论与实践
    EOS源码分析:transaction的一生
    勘误:EOS资源抵押退还
    如何踩中下一个技术节拍
    本人新书,欢迎抢购
    REX:EOS资源租赁平台详解
  • 原文地址:https://www.cnblogs.com/517cn/p/10938167.html
Copyright © 2011-2022 走看看