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

