java中的定時任務, 使用java實現有3種方式:html
@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(); }
線程安全, 但只會單線程執行, 若是執行時間過長, 就錯過下次任務了, 拋出異常時, 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); }
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); }
第一種方式, 註解的方式實現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觸發
maven依賴
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency>
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("定時任務執行中…"); } }
任務類:
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>
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("定時任務執行了"); } }
爲何非要集成呢, 由於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