zoukankan      html  css  js  c++  java
  • 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 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/wenbronk/p/6433178.html
Copyright © 2011-2022 走看看