這篇文章將為大家詳細(xì)講解有關(guān)Spring內(nèi)置任務(wù)調(diào)度實(shí)現(xiàn)添加、取消與重置的示例,小編覺得挺實(shí)用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
為達(dá)茂旗等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及達(dá)茂旗網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、達(dá)茂旗網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
實(shí)現(xiàn)方法如下
首先,我們需要啟用Spring的任務(wù)調(diào)度
<?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:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"> <task:annotation-driven executor="jobExecutor" scheduler="jobScheduler" /> <task:executor id="jobExecutor" pool-size="5"/> <task:scheduler id="jobScheduler" pool-size="10" /> </beans>
這一部分配置在網(wǎng)上是很常見的,接下來我們需要聯(lián)合使用@EnableScheduling與org.springframework.scheduling.annotation.SchedulingConfigurer便攜我們自己的調(diào)度配置,在SchedulingConfigurer接口中,需要實(shí)現(xiàn)一個void configureTasks(ScheduledTaskRegistrar taskRegistrar);方法,傳統(tǒng)做法是在該方法中添加需要執(zhí)行的調(diào)度信息。網(wǎng)上的基本撒謊那個也都是使用該方法實(shí)現(xiàn)的,使用addTriggerTask添加任務(wù),并結(jié)合cron表達(dá)式動態(tài)修改調(diào)度時間,這里我們并不這樣做。
查看一下ScheduledTaskRegistrar源碼,我們發(fā)現(xiàn)該對象初始化完成后會執(zhí)行scheduleTasks()方法,在該方法中添加任務(wù)調(diào)度信息,最終所有的任務(wù)信息都存放在名為scheduledFutures的集合中。
protected void scheduleTasks() {
long now = System.currentTimeMillis();
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (TriggerTask task : this.triggerTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(), task.getTrigger()));
}
}
if (this.cronTasks != null) {
for (CronTask task : this.cronTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(), task.getTrigger()));
}
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(), startTime, task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(), task.getInterval()));
}
}
}
if (this.fixedDelayTasks != null) {
for (IntervalTask task : this.fixedDelayTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(), startTime, task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(), task.getInterval()));
}
}
}
}所以我的思路就是動態(tài)修改該集合,實(shí)現(xiàn)任務(wù)調(diào)度的添加、取消、重置。實(shí)現(xiàn)代碼如下:
package com.jianggujin.web.util.job;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import com.jianggujin.web.util.BeanUtils;
/**
* 默認(rèn)任務(wù)調(diào)度配置
*
* @author jianggujin
*
*/
@EnableScheduling
public class DefaultSchedulingConfigurer implements SchedulingConfigurer
{
private final String FIELD_SCHEDULED_FUTURES = "scheduledFutures";
private ScheduledTaskRegistrar taskRegistrar;
private Set<ScheduledFuture<?>> scheduledFutures = null;
private Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<String, ScheduledFuture<?>>();
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
{
this.taskRegistrar = taskRegistrar;
}
@SuppressWarnings("unchecked")
private Set<ScheduledFuture<?>> getScheduledFutures()
{
if (scheduledFutures == null)
{
try
{
scheduledFutures = (Set<ScheduledFuture<?>>) BeanUtils.getProperty(taskRegistrar, FIELD_SCHEDULED_FUTURES);
}
catch (NoSuchFieldException e)
{
throw new SchedulingException("not found scheduledFutures field.");
}
}
return scheduledFutures;
}
/**
* 添加任務(wù)
*
* @param taskId
* @param triggerTask
*/
public void addTriggerTask(String taskId, TriggerTask triggerTask)
{
if (taskFutures.containsKey(taskId))
{
throw new SchedulingException("the taskId[" + taskId + "] was added.");
}
TaskScheduler scheduler = taskRegistrar.getScheduler();
ScheduledFuture<?> future = scheduler.schedule(triggerTask.getRunnable(), triggerTask.getTrigger());
getScheduledFutures().add(future);
taskFutures.put(taskId, future);
}
/**
* 取消任務(wù)
*
* @param taskId
*/
public void cancelTriggerTask(String taskId)
{
ScheduledFuture<?> future = taskFutures.get(taskId);
if (future != null)
{
future.cancel(true);
}
taskFutures.remove(taskId);
getScheduledFutures().remove(future);
}
/**
* 重置任務(wù)
*
* @param taskId
* @param triggerTask
*/
public void resetTriggerTask(String taskId, TriggerTask triggerTask)
{
cancelTriggerTask(taskId);
addTriggerTask(taskId, triggerTask);
}
/**
* 任務(wù)編號
*
* @return
*/
public Set<String> taskIds()
{
return taskFutures.keySet();
}
/**
* 是否存在任務(wù)
*
* @param taskId
* @return
*/
public boolean hasTask(String taskId)
{
return this.taskFutures.containsKey(taskId);
}
/**
* 任務(wù)調(diào)度是否已經(jīng)初始化完成
*
* @return
*/
public boolean inited()
{
return this.taskRegistrar != null && this.taskRegistrar.getScheduler() != null;
}
}其中用到的BeanUtils源碼如下:
package com.jianggujin.web.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BeanUtils
{
public static Field findField(Class<?> clazz, String name)
{
try
{
return clazz.getField(name);
}
catch (NoSuchFieldException ex)
{
return findDeclaredField(clazz, name);
}
}
public static Field findDeclaredField(Class<?> clazz, String name)
{
try
{
return clazz.getDeclaredField(name);
}
catch (NoSuchFieldException ex)
{
if (clazz.getSuperclass() != null)
{
return findDeclaredField(clazz.getSuperclass(), name);
}
return null;
}
}
public static Method findMethod(Class<?> clazz, String methodName, Class<?>... paramTypes)
{
try
{
return clazz.getMethod(methodName, paramTypes);
}
catch (NoSuchMethodException ex)
{
return findDeclaredMethod(clazz, methodName, paramTypes);
}
}
public static Method findDeclaredMethod(Class<?> clazz, String methodName, Class<?>... paramTypes)
{
try
{
return clazz.getDeclaredMethod(methodName, paramTypes);
}
catch (NoSuchMethodException ex)
{
if (clazz.getSuperclass() != null)
{
return findDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes);
}
return null;
}
}
public static Object getProperty(Object obj, String name) throws NoSuchFieldException
{
Object value = null;
Field field = findField(obj.getClass(), name);
if (field == null)
{
throw new NoSuchFieldException("no such field [" + name + "]");
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
try
{
value = field.get(obj);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
field.setAccessible(accessible);
return value;
}
public static void setProperty(Object obj, String name, Object value) throws NoSuchFieldException
{
Field field = findField(obj.getClass(), name);
if (field == null)
{
throw new NoSuchFieldException("no such field [" + name + "]");
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
try
{
field.set(obj, value);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
field.setAccessible(accessible);
}
public static Map<String, Object> obj2Map(Object obj, Map<String, Object> map)
{
if (map == null)
{
map = new HashMap<String, Object>();
}
if (obj != null)
{
try
{
Class<?> clazz = obj.getClass();
do
{
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields)
{
int mod = field.getModifiers();
if (Modifier.isStatic(mod))
{
continue;
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
field.setAccessible(accessible);
}
clazz = clazz.getSuperclass();
} while (clazz != null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
return map;
}
/**
* 獲得父類集合,包含當(dāng)前class
*
* @param clazz
* @return
*/
public static List<Class<?>> getSuperclassList(Class<?> clazz)
{
List<Class<?>> clazzes = new ArrayList<Class<?>>(3);
clazzes.add(clazz);
clazz = clazz.getSuperclass();
while (clazz != null)
{
clazzes.add(clazz);
clazz = clazz.getSuperclass();
}
return Collections.unmodifiableList(clazzes);
}
}因?yàn)榧虞d的延遲,在使用這種方法自定義配置任務(wù)調(diào)度是,首先需要調(diào)用inited()方法判斷是否初始化完成,否則可能出現(xiàn)錯誤。
接下來我們來測試一下:
package com.jianggujin.zft.job;
import java.util.Calendar;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.config.TriggerTask;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import com.jianggujin.web.util.job.DefaultSchedulingConfigurer;
public class TestJob implements InitializingBean
{
@Autowired
private DefaultSchedulingConfigurer defaultSchedulingConfigurer;
public void afterPropertiesSet() throws Exception
{
new Thread() {
public void run()
{
try
{
// 等待任務(wù)調(diào)度初始化完成
while (!defaultSchedulingConfigurer.inited())
{
Thread.sleep(100);
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("任務(wù)調(diào)度初始化完成,添加任務(wù)");
defaultSchedulingConfigurer.addTriggerTask("task", new TriggerTask(new Runnable() {
@Override
public void run()
{
System.out.println("run job..." + Calendar.getInstance().get(Calendar.SECOND));
}
}, new CronTrigger("0/5 * * * * ? ")));
};
}.start();
new Thread() {
public void run()
{
try
{
Thread.sleep(30000);
}
catch (Exception e)
{
}
System.out.println("重置任務(wù)............");
defaultSchedulingConfigurer.resetTriggerTask("task", new TriggerTask(new Runnable() {
@Override
public void run()
{
System.out.println("run job..." + Calendar.getInstance().get(Calendar.SECOND));
}
}, new CronTrigger("0/10 * * * * ? ")));
};
}.start();
}
}在該類中,我們首先使用一個線程,等待我們自己的任務(wù)調(diào)度初始化完成后向其中添加一個每五秒鐘打印一句話的任務(wù),然后再用另一個線程過30秒后修改該任務(wù),修改的本質(zhì)其實(shí)是現(xiàn)將原來的任務(wù)取消,然后再添加一個新的任務(wù)。
在配置文件中初始化上面的類
<bean id="defaultSchedulingConfigurer" class="com.jianggujin.web.util.job.DefaultSchedulingConfigurer"/> <bean id="testJob" class="com.jianggujin.zft.job.TestJob"/>
運(yùn)行程序,觀察控制臺輸出

這樣我們就實(shí)現(xiàn)了動態(tài)的重置任務(wù)了。
關(guān)于“Spring內(nèi)置任務(wù)調(diào)度實(shí)現(xiàn)添加、取消與重置的示例”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
網(wǎng)站名稱:Spring內(nèi)置任務(wù)調(diào)度實(shí)現(xiàn)添加、取消與重置的示例
瀏覽路徑:http://www.chinadenli.net/article4/peesie.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、云服務(wù)器、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)