java中的定時任務

java中的定時任務, 使用java實現有3種方式:html

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會終止java

@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種的額一個累, 用於實現定時任務redis

  它能夠: 1, 經過線程池的方式執行任務spring

      2, 設定第一次的延遲事件spring-mvc

      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 實現

   第一種方式, 註解的方式實現springboot

@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 * * ? ": 使用時間表達式
 

   第二種方式, 配置文件配置的方式實現mvc

 <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, 添加配置信息    maven

<!—開啓這個配置,spring才能識別@Scheduled註解   -->  
    <task:annotation-driven scheduler="qbScheduler" mode="proxy"/>  
    <task:scheduler id="qbScheduler" pool-size="10"/> 

    3, 代碼實現 ide

@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

相關文章
相關標籤/搜索