• java中的定时任务


    java中的定时任务, 使用java实现有3种方式:

    1, 使用普通thread实现

    复制代码
      @Test
      public void test1() {  
            // 单位: 毫秒
            final long timeInterval = 1000;  
            Runnable runnable = new Runnable() {  
                public void run() {  
                    while (true) {  
                        // ------- code for task to run  
                        System.out.println("Hello !!");  
                        // ------- ends here  
                        try {  
                            Thread.sleep(timeInterval);  
                        } catch (InterruptedException e) {  
                            e.printStackTrace();  
                        }  
                    }  
                }  
            };  
            Thread thread = new Thread(runnable);  
            thread.start();  
        } 
    复制代码

    2, 使用timer实现: 可控制启动或取消任务, 可指定第一次执行的延迟

      线程安全, 但只会单线程执行, 如果执行时间过长, 就错过下次任务了, 抛出异常时, timerWork会终止

    复制代码
    @Test
    public void test2 () {  
          TimerTask task = new TimerTask() {  
              @Override  
              public void run() {  
                 System.out.println("Hello !!!");  
              }  
          };  
          Timer timer = new Timer();  
          long delay = 0;  
          long intevalPeriod = 1 * 1000;  
          // schedules the task to be run in an interval  
          timer.scheduleAtFixedRate(task, delay, intevalPeriod);  
        }
    复制代码

    3, 使用 ScheduledExcecutorService 实现

      ScheduledExecutorService 是java.util.concurrent种的额一个累, 用于实现定时任务

      它可以: 1, 通过线程池的方式执行任务

          2, 设定第一次的延迟事件

          3, 提供良好的约定, 设定时间间隔

    复制代码
    @Test
    public void test() {
        Runnable runnable = new Runnable() {  
                public void run() {  
                    System.out.println("Hello !!");  
                }  
            };  
            ScheduledExecutorService service = Executors  
                    .newSingleThreadScheduledExecutor();  
            // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间  
            service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);  
        }  
    复制代码

    4, 使用spring的 spring-task 实现

       第一种方式, 注解的方式实现

    复制代码
    @Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.ANNOTATION_TYPE})  
    @Retention(RetentionPolicy.RUNTIME)  
    @Documented  
    public @interface Scheduled  
    {  
      public abstract String cron();  
      
      public abstract long fixedDelay();  
      
      public abstract long fixedRate();  
    }  

    fixedDelay: 设定间隔时间为 5000ms
    fixedRate: 设定固定速率, 以固定速率5s来执行
    cron="0 0 2 * * ? ": 使用时间表达式
     
    复制代码

       第二种方式, 配置文件配置的方式实现

     <task:scheduled-tasks>   
            <task:scheduled ref="taskJob" method="job1" cron="0 * * * * ?"/>   
    </task:scheduled-tasks>  
      /* taskJob 为执行任务类, job1 为执行的函数*/
    <context:component-scan base-package="com.wenbronk.mytask " />  

        2, 添加配置信息    

    <!—开启这个配置,spring才能识别@Scheduled注解   -->  
        <task:annotation-driven scheduler="qbScheduler" mode="proxy"/>  
        <task:scheduler id="qbScheduler" pool-size="10"/> 

        3, 代码实现 

    @Scheduled(fixedDelay = 5000)
    public void doSomething() { 
        // something that should execute periodically
    }

    时间表达式

    复制代码
    一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
    按顺序依次为
    秒(0~59)
    分钟(0~59)
    小时(0~23)
    天(月)(0~31,但是你需要考虑你月的天数)
    月(0~11)
    天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
    年份(1970-2099)
    复制代码

    常用的表达式为: 

    复制代码
    0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
    0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
    0 0 12 ? * WED 表示每个星期三中午12点 
    "0 0 12 * * ?" 每天中午12点触发 
    "0 15 10 ? * *" 每天上午10:15触发 
    "0 15 10 * * ?" 每天上午10:15触发 
    "0 15 10 * * ? *" 每天上午10:15触发 
    "0 15 10 * * ? 2005" 2005年的每天上午10:15触发 
    "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发 
    "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发 
    "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 
    "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发 
    "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发 
    "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发 
    "0 15 10 15 * ?" 每月15日上午10:15触发 
    "0 15 10 L * ?" 每月最后一日的上午10:15触发 
    "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发 
    "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 
    "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 
    复制代码

    5, 使用 第三方插件 Quartz实现

     maven依赖

        <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.1</version>
            </dependency>

    5. 1) 可以设置一个类, 继承自 QuartzJobBean

     1, 配置文件: 

    复制代码
        <!-- 配置作业类 -->
        <bean name="job1" class="org.springframework.scheduling.quartz.JobDetailBean">
            <property name="jobClass" value="com.gy.Job1" />
            <property name="jobDataAsMap">
                <map>
                    <entry key="timeout" value="0" />
                </map>
            </property>
        </bean>
    
        <!-- 配置触发方式 -->
        <!-- simpleTrggerBean 只支持一种方式调度 -->
        <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
            <property name="jobDetail" ref="job1" />
            <property name="startDelay" value="0" />  <!-- 调度工厂实例化后,经过0秒开始执行调度 -->
            <property name="repeatInterval" value="2000" />  <!-- 每2秒调度一次 -->
        </bean>
    
    
        <!-- 使用CronTrggerBean , 支持时间表达式 -->
        <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
            <property name="jobDetail" ref="job1" />  
            <!-- 每天12点运行一次 -->
            <property name="cronExpression" value="0 0 12 * * ?" />
        </bean>
    复制代码

      2, 配置调度工厂: 

    复制代码
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="triggers">
                <list>
                    <ref bean="cronTrigger" />
                </list>
            </property>
        </bean>
    复制代码

       3, 定义作业类: 

    复制代码
    public class Job1 extends QuartzJobBean {
            private int timeout;
            private static int i = 0;
            // 调度工厂实例化后,经过timeout时间开始执行调度
            public void setTimeout(int timeout) {
                this.timeout = timeout;
            }
            /**
             * 要调度的具体任务
             */
            @Override
            protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                System.out.println("定时任务执行中…");
            }
        }
    复制代码

    5.2) 直接写一个普通类, 在配置中进行配置 

      任务类: 

    复制代码
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    
    /**
     * 定时删除用户收听过的poi
     * @author wenbronk
     * @time 2017年3月28日  下午2:01:09  2017
     */
    public class DelListenerPOIScheduler {
    
        @Autowired
        private StringRedisTemplate redisTemplate;
        
        public void doCheck() {
            System.out.println("定时任务执行了....");
        }
        
    }
    复制代码

    配置文件: 

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
                            http://www.springframework.org/schema/tx
                            http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                            http://www.springframework.org/schema/mvc
                             http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-4.2.xsd">
                            
        <!-- 配置作业类 -->
        <bean id="delRedisListenerHistory" class="com.iwhere.easy.travel.valid.DelListenerPOIScheduler" />
    
        <!-- 作业类描述, 使用方法调度 -->
        <bean id="methodInvoking"
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="delRedisListenerHistory" />
            <property name="targetMethod" value="doCheck" />
        </bean>
    
        <!-- 触发器, 使用定时触发 -->
        <bean id="delTrigger"
            class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="methodInvoking" />
            <property name="cronExpression" value="0/10 * * * * ?" />
        </bean>
    
        <!-- 总调度器 -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="triggers">
                <list>
                    <ref bean="delTrigger" />
                </list>
            </property>
        </bean>
    
    </beans>
    复制代码

    6, 在springboot中实现定时任务: 

    复制代码
    package com.iwhere.base.scheduling;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    
    /**
     * 整合定时任务
     * EnableScheduling 实现spring中的task功能
     * @Scheduled中配置时间表达式
     * @author 231
     *
     */
    @Configuration        // 相当于配置beans, 
    @EnableScheduling    // <task:*>, 让spring进行任务调度
    public class SchedulingConfig {
    
        @Scheduled(cron="0/20 * * * * ?")    // 20秒执行一次
        public void scheduler() {
            System.out.println("定时任务执行了");
        }
        
    }
    复制代码

     7, Springboot 集成 quartz

    为什么非要集成呢, 因为quartz支持集群定时任务, 现在还用不到, 防止以后用到

    1, 配置quartz的配置信息类

    复制代码
    package com.iwhere.easy.travel.timeschedule;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
    import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    /**
     * quartz的配置信息
     * @author wenbronk
     * @time 2017年3月29日  下午5:20:29  2017
     */
    @Configuration 
    public class TimeScheduleConfig {
    
        @Bean(name = "detailFactoryBean")
        public MethodInvokingJobDetailFactoryBean detailFactoryBean(DelListenerPOIScheduler scheduledTasks) {
            MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
            // 这儿设置对应的Job对象
            bean.setTargetObject(scheduledTasks);
            // 这儿设置对应的方法名 与执行具体任务调度类中的方法名对应
            bean.setTargetMethod("doCheck");
            bean.setConcurrent(false);
            return bean;
        }
    
        @Bean(name = "cronTriggerBean")
        public CronTriggerFactoryBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean) {
            CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
            trigger.setJobDetail(detailFactoryBean.getObject());
            try {
                trigger.setCronExpression("0 0 1 * * ?");// 每天1点执行一次
            } catch (Exception e) {
                e.printStackTrace();
            }
            return trigger;
    
        }
    
        @Bean
        public SchedulerFactoryBean schedulerFactory(CronTriggerFactoryBean cronTriggerBean) {
            SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
            schedulerFactory.setTriggers(cronTriggerBean.getObject());
            return schedulerFactory;
        }
    
    }
    复制代码

    2), 具体的作业类

    复制代码
    package com.iwhere.easy.travel.timeschedule;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.stereotype.Component;
    
    /**
     * 定时删除用户收听过的poi
     * @author wenbronk
     * @time 2017年3月28日  下午2:01:09  2017
     */
    @Component  
    @Configurable  
    @EnableScheduling
    public class DelListenerPOIScheduler {
        private Logger LOGGER = LoggerFactory.getLogger(DelListenerPOIScheduler.class);
        
        @Autowired
        private StringRedisTemplate redisTemplate;
        
        public void doCheck() {
            
            try {
                String key = "noteUserListenedPoi:*";
                redisTemplate.delete(key);
                LOGGER.info("redis中用户收听历史被清空");
            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.error("redis删除用户收听记录失败");
            }
        }
        
    }
    复制代码

    系列原创, 转载请注明出处, 谢谢 @Wenbronk: http://www.cnblogs.com/wenbronk/p/6433178.html

  • 相关阅读:
    Android 在Java代码中设置style属性使用代码创建ProgressBar对象
    编写高效的Android代码(提高运行速度,节省电量)
    Android动态加载——加载已安装APK中的类
    使用NDK移植开源项目,JNI的使用技巧
    [随便写写]Android基础教程
    Android 通过按键旋转屏幕
    struts2中获取request、response,与android客户端进行交互
    Oracle配置监听和连接,已经一些比较容易混淆的相关概念
    Oracle Profile 使用详解
    VS.NET(VC++风格)常用快捷键 && UltraEdit常用快捷键
  • 原文地址:https://www.cnblogs.com/xiaofengfeng/p/9258617.html
Copyright © 2020-2023  润新知