最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring內(nèi)置任務(wù)調(diào)度如何實現(xiàn)添加、取消與重置詳解

 更新時間:2017年10月16日 08:35:50   作者:蔣固金  
任務(wù)調(diào)度是我們?nèi)粘i_發(fā)中經(jīng)常會碰到的,下面這篇文章主要給大家介紹了關(guān)于Spring內(nèi)置任務(wù)調(diào)度如何實現(xiàn)添加、取消與重置的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

大家應(yīng)該都有所體會,使用Spring的任務(wù)調(diào)度給我們的開發(fā)帶來了極大的便利,不過當(dāng)我們的任務(wù)調(diào)度配置完成后,很難再對其進行更改,除非停止服務(wù)器,修改配置,然后再重啟,顯然這樣是不利于線上操作的,為了實現(xiàn)動態(tài)的任務(wù)調(diào)度修改,我在網(wǎng)上也查閱了一些資料,大部分都是基于quartz實現(xiàn)的,使用Spring內(nèi)置的任務(wù)調(diào)度則少之又少,而且效果不理想,需要在下次任務(wù)執(zhí)行后,新的配置才能生效,做不到立即生效。本著探索研究的原則,查看了一下Spring的源碼,下面為大家提供一種Spring內(nèi)置任務(wù)調(diào)度實現(xiàn)添加、取消、重置的方法。話不多說了,來一起看看詳細的介紹 吧。

實現(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接口中,需要實現(xiàn)一個void configureTasks(ScheduledTaskRegistrar taskRegistrar);方法,傳統(tǒng)做法是在該方法中添加需要執(zhí)行的調(diào)度信息。網(wǎng)上的基本撒謊那個也都是使用該方法實現(xiàn)的,使用addTriggerTask添加任務(wù),并結(jié)合cron表達式動態(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)修改該集合,實現(xiàn)任務(wù)調(diào)度的添加、取消、重置。實現(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;

/**
 * 默認任務(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);
 }
}

因為加載的延遲,在使用這種方法自定義配置任務(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ì)其實是現(xiàn)將原來的任務(wù)取消,然后再添加一個新的任務(wù)。

在配置文件中初始化上面的類

<bean id="defaultSchedulingConfigurer" class="com.jianggujin.web.util.job.DefaultSchedulingConfigurer"/>
<bean id="testJob" class="com.jianggujin.zft.job.TestJob"/>

運行程序,觀察控制臺輸出

這樣我們就實現(xiàn)了動態(tài)的重置任務(wù)了。以上為個人探索出來的方法,如有更好的解決方案,歡迎指正。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Java中LinkedHashMap的實現(xiàn)詳解

    Java中LinkedHashMap的實現(xiàn)詳解

    LinkedHashMap是Java中的一個Map容器,它繼承自HashMap,并且還可以對元素進行有序存儲,本文將介紹LinkedHashMap的實現(xiàn)原理以及使用方法,并且提供相應(yīng)的測試用例和全文小結(jié),需要的可以參考下
    2023-09-09
  • Java關(guān)鍵字this與super詳解用法

    Java關(guān)鍵字this與super詳解用法

    這篇文章主要介紹了Java關(guān)鍵字this與super的用法,this與super是類實例化時通往Object類通道的打通者;this和super在程序中由于其經(jīng)常被隱式的使用而被我們忽略,但是理解其作用和使用規(guī)范肯定是必須的。接下來將詳述this與super各自的的作用,需要的朋友可以參考一下
    2022-04-04
  • 關(guān)于Lists.partition集合分組使用以及注意事項

    關(guān)于Lists.partition集合分組使用以及注意事項

    這篇文章主要介紹了關(guān)于Lists.partition集合分組使用以及注意事項,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 面向切面的Spring通過切點來選擇連接點實例詳解

    面向切面的Spring通過切點來選擇連接點實例詳解

    這篇文章主要為大家介紹了面向切面的Spring通過切點來選擇連接點實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Java的SPI機制以及基于SPI編程示例詳解

    Java的SPI機制以及基于SPI編程示例詳解

    這篇文章主要為大家介紹了Java的SPI機制以及基于SPI編程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • java中使用DES加密解密實例

    java中使用DES加密解密實例

    這篇文章主要介紹了java中使用DES加密解密實例,需要的朋友可以參考一下
    2014-01-01
  • 如何通過jstack命令dump線程信息

    如何通過jstack命令dump線程信息

    這篇文章主要介紹了如何通過jstack命令dump線程信息,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫

    Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫

    在開發(fā)中,我們經(jīng)常會遇到這樣的需求,將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫中,這篇文章主要來和大家講講Java如何使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫,感興趣的可以了解下
    2024-01-01
  • Java利用Optional解決空指針異常

    Java利用Optional解決空指針異常

    這篇文章主要介紹了Java利用Optional解決空指針異常,Optional?類是一個包含有可選值的包裝類,這意味著?Optional?類既可以含有對象也可以為空
    2022-09-09
  • Java Spring Controller 獲取請求參數(shù)的幾種方法詳解

    Java Spring Controller 獲取請求參數(shù)的幾種方法詳解

    這篇文章主要介紹了Java Spring Controller 獲取請求參數(shù)的幾種方法詳解的相關(guān)資料,這里提供了6種方法,需要的朋友可以參考下
    2016-12-12

最新評論

屏东县| 鲁甸县| 砚山县| 灵武市| 阿坝县| 邹平县| 洪江市| 舒兰市| 大石桥市| 巴南区| 普宁市| 疏附县| 东山县| 定边县| 江达县| 鞍山市| 镇巴县| 武义县| 沙雅县| 班玛县| 农安县| 榆社县| 建瓯市| 萝北县| 平山县| 黄山市| 双柏县| 静安区| 仪陇县| 阳原县| 阜南县| 蛟河市| 深泽县| 文昌市| 南江县| 金山区| 巨鹿县| 丰原市| 抚宁县| 宁明县| 安仁县|