一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring內置任務調度如何實現添加、取消與重置詳解

Spring內置任務調度如何實現添加、取消與重置詳解

2021-01-18 10:17蔣固金 Java教程

任務調度是我們日常開發中經常會碰到的,下面這篇文章主要給大家介紹了關于Spring內置任務調度如何實現添加、取消與重置的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學

前言

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

實現方法如下

首先,我們需要啟用Spring的任務調度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>

這一部分配置在網上是很常見的,接下來我們需要聯合使用@EnableScheduling與org.springframework.scheduling.annotation.SchedulingConfigurer便攜我們自己的調度配置,在SchedulingConfigurer接口中,需要實現一個void configureTasks(ScheduledTaskRegistrar taskRegistrar);方法,傳統做法是在該方法中添加需要執行的調度信息。網上的基本撒謊那個也都是使用該方法實現的,使用addTriggerTask添加任務,并結合cron表達式動態修改調度時間,這里我們并不這樣做。

查看一下ScheduledTaskRegistrar源碼,我們發現該對象初始化完成后會執行scheduleTasks()方法,在該方法中添加任務調度信息,最終所有的任務信息都存放在名為scheduledFutures的集合中。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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()));
    }
   }
  }
 }

所以我的思路就是動態修改該集合,實現任務調度的添加、取消、重置。實現代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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;
 
/**
 * 默認任務調度配置
 *
 * @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;
 }
 
 /**
 * 添加任務
 *
 * @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);
 }
 
 /**
 * 取消任務
 *
 * @param taskId
 */
 public void cancelTriggerTask(String taskId)
 {
  ScheduledFuture<?> future = taskFutures.get(taskId);
  if (future != null)
  {
   future.cancel(true);
  }
  taskFutures.remove(taskId);
  getScheduledFutures().remove(future);
 }
 
 /**
 * 重置任務
 *
 * @param taskId
 * @param triggerTask
 */
 public void resetTriggerTask(String taskId, TriggerTask triggerTask)
 {
  cancelTriggerTask(taskId);
  addTriggerTask(taskId, triggerTask);
 }
 
 /**
 * 任務編號
 *
 * @return
 */
 public Set<String> taskIds()
 {
  return taskFutures.keySet();
 }
 
 /**
 * 是否存在任務
 *
 * @param taskId
 * @return
 */
 public boolean hasTask(String taskId)
 {
  return this.taskFutures.containsKey(taskId);
 }
 
 /**
 * 任務調度是否已經初始化完成
 *
 * @return
 */
 public boolean inited()
 {
  return this.taskRegistrar != null && this.taskRegistrar.getScheduler() != null;
 }
}

其中用到的BeanUtils源碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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;
 }
 
 /**
 * 獲得父類集合,包含當前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);
 }
}

因為加載的延遲,在使用這種方法自定義配置任務調度是,首先需要調用inited()方法判斷是否初始化完成,否則可能出現錯誤。

接下來我們來測試一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
   {
    // 等待任務調度初始化完成
    while (!defaultSchedulingConfigurer.inited())
    {
     Thread.sleep(100);
    }
   }
   catch (InterruptedException e)
   {
    e.printStackTrace();
   }
   System.out.println("任務調度初始化完成,添加任務");
   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("重置任務............");
   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();
 }
}

在該類中,我們首先使用一個線程,等待我們自己的任務調度初始化完成后向其中添加一個每五秒鐘打印一句話的任務,然后再用另一個線程過30秒后修改該任務,修改的本質其實是現將原來的任務取消,然后再添加一個新的任務。

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

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

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

Spring內置任務調度如何實現添加、取消與重置詳解

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:http://blog.csdn.net/jianggujin/article/details/77937316

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 草逼网站视频 | 亚洲AV无码国产精品色午夜情 | 国产丰满美女做爰 | 国产人妖ts在线视频网 | 日本 片 成人 在线 日b视频免费 | 青青自拍视频 | 攻插受| 肉肉小说在线阅读 | 色哟哟哟在线精品观看视频 | 国产成人亚洲精品乱码在线观看 | 2021最新国产成人精品免费 | caoporn国产| 日本全黄三级在线观看 | 欧美贵妇vs高跟办公室 | 欧美精品成人a多人在线观看 | 高h舔穴 | 动漫美女被吸乳羞羞小说 | 日本 片 成人 在线 日b视频免费 | 国产精品免费久久久久影院 | 日韩精品视频在线观看免费 | 欧美一区二区三区四区五区六区 | 精久久 | 国产传媒天美果冻 | 91精品免费国产高清在线 | 国产精品久久久久久久久免费观看 | 欧美亚洲一区二区三区在线 | 女人肮脏的交易中文字幕未删减版 | 免费超级乱淫播放手机版 | 9色视频在线观看 | videos欧美肥婆 | 亚洲一区二区精品推荐 | 久久婷婷五月综合色丁香 | 百合漫画咱啪全彩抚慰 | 边摸边吃奶边做爽视频免费 | 草久网| 天生奶水1v1高h | 人人澡 人人澡碰人人看软件 | 高清毛片aaaaaaaaa片 | 秋霞在线观看成人高清视频51 | 免费又爽又黄禁片视频在线播放 | 亚洲国产货青视觉盛宴 |