java电商订单超时改状态工具类
最近在做一个电商项目,要求在用户下单后未付款30分钟后就将订单的状态改为失效,最初想的是用定时器没几秒去数据库查看有哪些订单未付款但超过30分的,就修改状态,这个方式有两种缺点,一:如果时间设置的较短,就会导致一直在读写数据库,二:如果时间设置较长就会导致时间不精确,所以就想到自己写一个工具类。
订单失效思想:当第一次有人下单时,启动定时器,延长半个小时后的时间作为定时器Timer的安排时间,当下第二个订单时检测,(第一个 订单的失效时间始终要比第二个订单失效时间少)是否创建了这个定时器,如果创建个就不管了,如果没有创建就创建,当在执行定时器任务,先判断这个订单是不是还是未付款状态,如果是就将状态改为失效,接着检测所有未付款订单里最先下单的时间读出 来加上30钟作为下一次定时器的执行时间,这样做就可以减轻服务器和数据库的压力。
如上面所说只用写一个简单的类就能完成了,在写的时候我觉得把他写成一个工具类,方便以后用,下面是代码:
首先想想到的是时间类型:时间有毫秒值间隔,时间类Date,还有cron表达式
前两种比较简单,而cron表达式比较麻烦,所以就简单的写了一下cron表达式解析(不完全,算一个最基本的解析):
简易cron表达式解析:
/**
* 解析corn表达式,将表达式所有的(秒,分,时,日,月,星期,年)可能性存在Map里
* 表达式可以为:x x-y x/y [x,x1,x2]
* @param cron
* @return
*/
public static Map<String, List<Integer>> parsingCron(String cron) {
String[] strings = cron.split(" ");
List<String> stringList = new ArrayList<>();
for (String s : strings) {
stringList.add(s);
}
if (stringList.contains("")) {
System.out.println("stringList:" + stringList);
System.out.println("表达是中有多余的空值,即将清除");
while (stringList.remove("")) ;
System.out.println("已移除多余的空值");
}
if (stringList.size() > 7) {
throw new RuntimeException("表达是不正确:超长");
}
//过短的表达式,补*号
while (stringList.size() != 7) {
stringList.add("*");
}
System.out.println("stringList:" + stringList);
Map<String, List<Integer>> map = new HashMap<>();
for (int i = 0; i < 7; i++) {
switch (i) {
case 0:
map.put("秒", readOneCronValue("秒", stringList.get(0), 59, 0));
break;
case 1:
map.put("分", readOneCronValue("分", stringList.get(1), 59, 0));
break;
case 2:
map.put("时", readOneCronValue("时", stringList.get(2), 23, 0));
break;
case 3:
map.put("日", readOneCronValue("日", stringList.get(3), 31, 1));
break;
case 4:
map.put("月", readOneCronValue("月", stringList.get(4), 12, 1));
break;
case 5:
map.put("星期", readOneCronValue("星期", stringList.get(5), 7, 1));
break;
case 6:
map.put("年", readOneCronValue("年", stringList.get(6), 2099, 1970));
break;
}
}
System.out.println(map);
return map;
}
/**
* 表达式可能性值处理方法
* 如果表达式里有字母会抛转换异常
* @param name
* @param str
* @param max
* @param min
* @return
*/
public static List<Integer> readOneCronValue(String name, String str, Integer max, Integer min) {
System.out.println(name + " :" + str);
List<Integer> integerList = new ArrayList<>();
if (str.contains("/")) {
String[] stringSplit = str.split("/");
if (stringSplit.length > 2) {
throw new RuntimeException(name + "格式不正确应为:y+/x+");
}
for (String s : stringSplit) {
maxAndMin(name, Integer.parseInt(s), max, min);
}
int addend = Integer.parseInt(stringSplit[0]), augend = Integer.parseInt(stringSplit[1]), and = addend + augend;
integerList.add(addend);
while (and < max) {
integerList.add(and);
and += augend;
}
} else if (str.contains("-")) {
String[] stringSplit = str.split("-");
int max1 = 0, min1 = Integer.MAX_VALUE, value = 0;
for (String s : stringSplit) {
value = maxAndMin(name, Integer.parseInt(s), max, min);
if (max1 < value) {
max1 = value;
}
if (min1 > value) {
min1 = value;
}
}
for (int i = min1; i <= max1; i++) {
integerList.add(i);
}
} else if (str.contains("[") && str.contains("]")) {
str = str.substring(1, str.length() - 1);
String[] strings = str.split(",");
for (String s : strings) {
integerList.add(maxAndMin(name, Integer.parseInt(s), max, min));
}
} else if (str.contains("*")) {
for (int i = min; i <= max; i++) {
integerList.add(i);
}
} else {
integerList.add(maxAndMin(name, Integer.parseInt(str), max, min));
}
//对数据进行排序(从小到大)
Collections.sort(integerList);
return integerList.size() == 0 ? null : integerList;
}
private static Integer maxAndMin(String name, Integer value, Integer max, Integer min) {
if ((value > max) || (value < min)) {
throw new RuntimeException((name != null ? name : "") + ":数值过小或过大:" + value);
}
return value;
}
定义时间类:
/**
* 时间类型类
*/
public static class TimerTaskType {
private Long timeValue; //间隔
private String timeCron; //cron表达是
private Date date; //时间类型
private Long number; //运行的次数
private Date runTime = new Date(); //运行时间
private Map<String, List<Integer>> cronTimeMap;
//提高效率增加的数值(cron表达式用到value)
private Integer[] theVariousTimeSize = new Integer[7];
private Integer[] runcronTimeMapStep = new Integer[7];
private String cronTimerString;
//销毁标识(当时间有问题时)
private Boolean theDestructionFlag = false;
public TimerTaskType() {
}
public TimerTaskType(Long timeValue, Long number) {
this.timeValue = timeValue;
this.number = number;
updateTime();
}
public TimerTaskType(String timeCron, Long number) {
this.timeCron = timeCron;
this.number = number;
cronTimeMap = parsingCron(timeCron);
cornInit();
}
public TimerTaskType(Date date, Long number) {
this.date = date;
this.number = number;
if (!objectNoNull(this.number)) {
this.number = 1L;
}
updateTime();
}
public static TimerTaskType getTimerTaskType(Long timeValue, Long number) {
return new TimerTaskType(timeValue, number);
}
public static TimerTaskType getTimerTaskType(String timeCron, Long number) {
return new TimerTaskType(timeCron, number);
}
public static TimerTaskType getTimerTaskType(Date date, Long number) {
return new TimerTaskType(date, number);
}
public Long getTimeValue() {
return timeValue;
}
public Boolean getTheDestructionFlag() {
return theDestructionFlag;
}
/**
* cron表达式初始化
*/
public void cornInit() {
List<Integer> secondList = cronTimeMap.get("秒");
List<Integer> minuteList = cronTimeMap.get("分");
List<Integer> hourOfDayList = cronTimeMap.get("时");
List<Integer> dayOfMonthList = cronTimeMap.get("日");
List<Integer> monthList = cronTimeMap.get("月");
List<Integer> dayOfWeekInMonthList = cronTimeMap.get("星期");
List<Integer> yearList = cronTimeMap.get("年");
theVariousTimeSize[0] = secondList.size();
theVariousTimeSize[1] = minuteList.size();
theVariousTimeSize[2] = hourOfDayList.size();
theVariousTimeSize[3] = dayOfMonthList.size();
theVariousTimeSize[4] = monthList.size();
theVariousTimeSize[5] = dayOfWeekInMonthList.size();
theVariousTimeSize[6] = yearList.size();
// System.out.println("theVariousTimeSize:" + Arrays.toString(theVariousTimeSize));
// System.out.println("=================================================");
// System.out.println("当前时间为:" + oftenDateToStringMs(new Date()));
// System.out.println("=================================================");
Calendar calendar = Calendar.getInstance();
//赋值runcronTimeMapStep
writeRuncronTimeMapStep(secondList, calendar.get(Calendar.SECOND), 0);
writeRuncronTimeMapStep(minuteList, calendar.get(Calendar.MINUTE), 1);
writeRuncronTimeMapStep(hourOfDayList, calendar.get(Calendar.HOUR_OF_DAY), 2);
writeRuncronTimeMapStep(dayOfMonthList, calendar.get(Calendar.DAY_OF_MONTH), 3);
writeRuncronTimeMapStep(monthList, calendar.get(Calendar.MONTH) + 1, 4);
writeRuncronTimeMapStep(yearList, calendar.get(Calendar.YEAR), 6);
theDateOfAndWeek();
runTime = cornTheAssemblyDate();
}
private Integer writeRuncronTimeMapStep(List<Integer> list, int value, int index) {
// System.out.println("当前值为:" + value);
if (list.contains(value)) {
runcronTimeMapStep[index] = list.indexOf(value);
} else {
for (int x = 0; x < index; x++) {
runcronTimeMapStep[x] = 0;
}
for (int i = 0; i < theVariousTimeSize[index]; i++) {
if (list.get(i) > value) {
runcronTimeMapStep[index] = i;
break;
}
}
if (runcronTimeMapStep[index] == null) {
if (index == 6) {
this.number = 1L;
runcronTimeMapStep[index] = 0;
} else {
runcronTimeMapStep[index] = 0;
}
}
}
return list.get(runcronTimeMapStep[index]);
// System.out.println("下标" + index + "值为:" + runcronTimeMapStep[index]);
}
/**
* 日期与星期的交集
*/
public void theDateOfAndWeek() {
if (theDestructionFlag) {
return;
}
List<Integer> dayOfWeekInMonthList = cronTimeMap.get("星期");
Date date = cornTheAssemblyDate();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int theDateOf = calendar.get(Calendar.DAY_OF_WEEK) - 1;
theDateOf = theDateOf == 0 ? 7 : theDateOf;
if (!dayOfWeekInMonthList.contains(theDateOf)) {
theDateOfChangeMonth();
theDateOfAndWeek();
}
}
/**
* 组装cron
*
* @return
*/
private Date cornTheAssemblyDate() {
// System.out.println("*************************************************");
List<List<Integer>> lists = new ArrayList<>();
lists.add(cronTimeMap.get("秒"));
lists.add(cronTimeMap.get("分"));
lists.add(cronTimeMap.get("时"));
lists.add(cronTimeMap.get("日"));
lists.add(cronTimeMap.get("月"));
lists.add(cronTimeMap.get("星期"));
lists.add(cronTimeMap.get("年"));
cronTimerString = "";
for (int i = 6; i > -1; i--) {
if (i != 5) {
writeTeimerString(lists.get(i), i);
}
}
// System.out.println("*************************************************");
return stringToDate("yyyy-MM-dd-HH-mm-ss", cronTimerString);
}
/**
*
* @param list
* @param index
*/
private void writeTeimerString(List<Integer> list, int index) {
String str = list.get(runcronTimeMapStep[index]).toString() + "-";
cronTimerString += str;
if (index == 0) {
cronTimerString = cronTimerString.substring(0, cronTimerString.length() - 1);
System.out.println("cronTimerString时间:" + cronTimerString);
}
}
/**
* 日,月,年处理
*/
public void theDateOfChangeMonth() {
//日
runcronTimeMapStep[3]++;
runcronTimeMapStep[2] = 0;
runcronTimeMapStep[1] = 0;
runcronTimeMapStep[0] = 0;
if (runcronTimeMapStep[3] >= theVariousTimeSize[3]) {
//月
runcronTimeMapStep[4]++;
runcronTimeMapStep[3] = 0;
if (runcronTimeMapStep[4] >= theVariousTimeSize[4]) {
//年
runcronTimeMapStep[6]++;
runcronTimeMapStep[4] = 0;
if (runcronTimeMapStep[6] >= theVariousTimeSize[6]) {
//防止发生错误
runcronTimeMapStep[6] = 0;
number = 1L;
//销毁标准
theDestructionFlag = true;
System.out.println("年的值达到上限,或月和星期有冲突");
}
}
}
}
/**
* 返回cron时间
*
* @return
*/
public Date getCornToTime() {
//秒
runcronTimeMapStep[0]++;
if (runcronTimeMapStep[0] >= theVariousTimeSize[0]) {
//分
runcronTimeMapStep[1]++;
runcronTimeMapStep[0] = 0;
if (runcronTimeMapStep[1] >= theVariousTimeSize[1]) {
//时
runcronTimeMapStep[2]++;
runcronTimeMapStep[1] = 0;
if (runcronTimeMapStep[2] >= theVariousTimeSize[2]) {
theDateOfChangeMonth();
theDateOfAndWeek();
}
}
}
return cornTheAssemblyDate();
}
public Date getDate() {
return date;
}
public Long getNumber() {
return number;
}
/**
* 返回运行时间
*
* @return
*/
public Date getRunTime() {
return this.runTime;
}
/**
* 更新时间
*/
public void updateTime() {
if (objectNoNull(timeValue)) {
this.runTime = new Date(runTime.getTime() + timeValue);
} else if (objectNoNull(timeCron)) {
this.runTime = getCornToTime();
} else {
this.runTime = date;
}
}
/**
* 次数运行是否到0
*
* @return
*/
public Boolean getYesAndNoRun() {
if (objectNoNull(number)) {
if ((--number) == 0) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "TimerTaskType{" +
"timeValue=" + timeValue +
", timeCron='" + timeCron + '\'' +
", date=" + date +
", number=" + number +
'}';
}
}
定义运行任务类:
/**
* 外部的任务类,要使用类继承字本类后才能用做着个工具任务
*/
public static abstract class TimerRunClass {
//一些存储数据的变量,当不用存值是可以无视
protected String stringValue;
protected Long longValue;
protected Integer intValue;
protected List<Object> objectListVlaue;
protected Object objectValue;
//运行这次任务的时间
protected Date runTime;
public String getStringValue() {
return stringValue;
}
public Long getLongValue() {
return longValue;
}
public Integer getIntValue() {
return intValue;
}
public List<Object> getObjectListVlaue() {
return objectListVlaue;
}
public Object getObjectValue() {
return objectValue;
}
/**
* 组装值
*
* @param obj
*/
public final void setAllTypeValue(Object obj) {
if (obj instanceof String) {
this.stringValue = (String) obj;
} else if (obj instanceof Long) {
this.longValue = (Long) obj;
} else if (obj instanceof List) {
objectListVlaue = (List<Object>) obj;
} else if (obj instanceof Integer) {
intValue = (Integer) obj;
} else {
objectValue = obj;
}
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public void setLongValue(Long longValue) {
this.longValue = longValue;
}
public void setIntValue(Integer intValue) {
this.intValue = intValue;
}
public void setObjectListVlaue(List<Object> objectListVlaue) {
this.objectListVlaue = objectListVlaue;
}
public void setObjectValue(Object objectValue) {
this.objectValue = objectValue;
}
public void setRunTime(Date runTime) {
this.runTime = runTime;
}
/**
* 时间运行任务函数
*/
public abstract void run();
/**
* 修改当前任务时间
*
* @return
*/
public TimerTaskType modifyTheTimeTask() {
return null;
}
/**
* 添加时间
*
* @return
*/
public TaskSchedulingClass addTimeTask() {
return null;
}
}
定义工具类使用的任务类:
/**
* 任务调度对象
*/
public static class TaskSchedulingClass implements Comparable<TaskSchedulingClass> {
private String thisaName;
private TimerTaskType timerTaskType;
private TimerRunClass timerRunClass;
public TaskSchedulingClass() {
}
public TaskSchedulingClass(String thisaName, TimerTaskType timerTaskType, TimerRunClass timerRunClass) {
this.thisaName = thisaName;
this.timerTaskType = timerTaskType;
this.timerRunClass = timerRunClass;
}
public String getThisaName() {
return thisaName;
}
public TimerTaskType getTimerTaskType() {
return timerTaskType;
}
public TimerRunClass getTimerRunClass() {
return timerRunClass;
}
public void setThisaName(String thisaName) {
this.thisaName = thisaName;
}
public void setTimerTaskType(TimerTaskType timerTaskType) {
this.timerTaskType = timerTaskType;
}
public void setTimerRunClass(TimerRunClass timerRunClass) {
this.timerRunClass = timerRunClass;
}
/**
* 运行
*/
public void run() {
this.timerRunClass.run();
TimerTaskType timerTaskType = this.timerRunClass.modifyTheTimeTask();
if (objectNoNull(timerTaskType)) {
if (objectNoNull(timerTaskType.number)) {
timerTaskType.number++;
}
this.timerTaskType = timerTaskType;
}
TaskSchedulingClass taskSchedulingClass = this.timerRunClass.addTimeTask();
if (objectNoNull(taskSchedulingClass)) {
addTaskScheduling(taskSchedulingClass);
}
if (this.timerTaskType.getYesAndNoRun() || this.timerTaskType.getTheDestructionFlag()) {
System.out.println("自销毁");
taskSchedulingList.remove(this);
} else {
this.timerTaskType.updateTime();
}
}
@Override
public int compareTo(TaskSchedulingClass taskSchedulingClass) {
if (this == taskSchedulingClass) {
return 0;
} else {
return ((Long) (this.timerTaskType.getRunTime().getTime() - taskSchedulingClass.timerTaskType.getRunTime().getTime())).intValue();
}
}
}
到这里就可以写工具类了:
public class TimerUtils {
//任务调度集合
private static List<TaskSchedulingClass> taskSchedulingList = new ArrayList<TaskSchedulingClass>();
//唯一的供任务调用的定时器
private static Timer taskTimer = new Timer();
//要运行的任务
private static List<TaskSchedulingClass> theRunTasks;
//要运行的时间
private static Date runTime;
private static Boolean runFlag = false;
private String test;
/**
* 增加一个任务
*
* @param timeName
* @param timerTaskType
* @param timerRunClass
* @return
*/
public static synchronized Boolean addTaskScheduling(String timeName, TimerTaskType timerTaskType, TimerRunClass timerRunClass) {
return addTaskScheduling(new TaskSchedulingClass(timeName, timerTaskType, timerRunClass));
}
/**
* 增加一个任务
*
* @param taskSchedulingClass
* @return
*/
public static synchronized Boolean addTaskScheduling(TaskSchedulingClass taskSchedulingClass) {
if (nameYesAndNoThereAre(taskSchedulingClass.getThisaName())) {
System.out.println("此定时器已存在,添加无效");
return false;
}
if (taskSchedulingClass.getTimerTaskType().getTheDestructionFlag()) {
System.out.println("此任务时间类销毁标志打开了,无法添加任务");
return false;
}
taskSchedulingList.add(taskSchedulingClass);
if (runFlag) {
if (runTime.getTime() > taskSchedulingClass.getTimerTaskType().getRunTime().getTime()) {
newTaskTimer();
startTaskTimer();
}
} else {
startTaskTimer();
runFlag = true;
}
return true;
}
/**
* 检测这样的定时器是否存在
*
* @param name
* @return
*/
public static Boolean nameYesAndNoThereAre(String name) {
for (TaskSchedulingClass t : taskSchedulingList) {
if (t.getThisaName().equals(name)) {
return true;
}
}
return false;
}
/**
* 更新
*
* @param name
* @param timerTaskType
* @return
*/
public static Boolean updateNmaeTimerTime(String name, TimerTaskType timerTaskType) {
System.out.println("更新:" + name);
for (TaskSchedulingClass t : taskSchedulingList) {
if (t.getThisaName().equals(name)) {
t.setTimerTaskType(timerTaskType);
//如果时间小于运行时间就进行调度更新
if ((runTime.getTime() > timerTaskType.getRunTime().getTime()) || (theRunTasks.contains(t))) {
newTaskTimer();
startTaskTimer();
}
return true;
}
}
return false;
}
/**
* 启动定时器
*/
public static void startTaskTimer() {
if (taskSchedulingList.size() > 0) {
forTaskForScheduling();
if (taskSchedulingList.size() > 0) {
taskTimer.schedule(getTimerTask(theRunTasks), runTime);
}
} else {
stopTaskTimer();
}
}
/**
* 更新运行任务
*/
public static void newTaskTimer() {
runTime = null;
theRunTasks = null;
stopTaskTimer();
}
/**
* 停止定时器
*/
public static void stopTaskTimer() {
taskTimer.cancel();
taskTimer = new Timer();
runFlag = false;
}
/**
* 清除所有任务
*/
public static void deleteAllTask() {
taskSchedulingList = new ArrayList<TaskSchedulingClass>();
}
/**
* 任务调度
*
* @return
*/
public static Boolean forTaskForScheduling() {
List<TaskSchedulingClass> taskList = new ArrayList<TaskSchedulingClass>();
TaskSchedulingClass min = Collections.min(taskSchedulingList);
runTime = min.getTimerTaskType().getRunTime();
Iterator<TaskSchedulingClass> iterator = taskSchedulingList.iterator();
while (iterator.hasNext()) {
TaskSchedulingClass next = iterator.next();
if (next.compareTo(min) == 0) {
taskList.add(next);
}
}
System.out.println("定时器里还有:" + taskSchedulingList.size() + "个任务");
//向运行类里写入运行时间
if (taskList.size() != 0) {
for (TaskSchedulingClass t : taskList) {
t.getTimerRunClass().setRunTime(runTime);
}
}
theRunTasks = taskList;
return true;
}
/**
* 返回一个TimerTask供Timer调用
*
* @param taskSchedulingClasss
* @return
*/
public static synchronized TimerTask getTimerTask(final List<TaskSchedulingClass> taskSchedulingClasss) {
return new TimerTask() {
@Override
public void run() {
// System.out.println(taskSchedulingClasss.size());
//这里的taskSchedulingClasss在java1.8以前的要加final关键字
for (TaskSchedulingClass t : taskSchedulingClasss) {
t.run();
}
startTaskTimer();
}
};
}
private static Boolean objectNoNull(Object obj) {
if (obj != null) {
return true;
}
return false;
}
/**
* 以下是附加的方便时间格式化显示
*/
/**
* 常用
*
* @param string
* @return
*/
private static Long oftenStringToTimeMs(String string) {
return stringToTime("yyyy-MM-dd HH:mm:ss", string);
}
private static String oftenDateToStringMs(Date date) {
return dateToString("yyyy-MM-dd HH:mm:ss", date);
}
/**
* 字符串格式时间转毫秒值
*
* @param format
* @param value
* @return
*/
public static Long stringToTime(String format, String value) {
return stringToDate(format, value).getTime();
}
/**
* 字符串格式时间转Date
*
* @param format
* @param value
* @return
*/
public static Date stringToDate(String format, String value) {
SimpleDateFormat sdft = new SimpleDateFormat(format);
Date date = null;
try {
date = sdft.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
/**
* Date时间转字符串
*
* @param format
* @param date
* @return
*/
public static String dateToString(String format, Date date) {
SimpleDateFormat sdft = new SimpleDateFormat(format);
String str = null;
str = sdft.format(date);
return str;
}
}
到此处工具类就写完了。
运行例子:
定义一个运行类继承TimerRunClass:
public class MyRun extends TimerUtils.TimerRunClass {
private String name;
private int i = 0;
public MyRun() {
}
public MyRun(String name) {
this.name = name;
}
@Override
public void run() {
i++;
System.out.println(i + "运行:" + name);
}
}
写一个main函数:
public class Demo {
public static void main(String[] args) throws InterruptedException {
TimerUtils.TimerTaskType timerTaskType = TimerUtils.TimerTaskType.getTimerTaskType("[10,20,30,40,50] * * * * * *", null);
TimerUtils.addTaskScheduling("订单", timerTaskType, new MyRun("程序"));
}
}
运行效果如下:
stringList:[[10,20,30,40,50], *, *, *, *, *, *]
秒 :[10,20,30,40,50]
分 :*
时 :*
日 :*
月 :*
星期 :*
年 :*
{秒=[10, 20, 30, 40, 50], 年=[1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099], 日=[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], 分=[0, 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], 时=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 月=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 星期=[1, 2, 3, 4, 5, 6, 7]}
cronTimerString时间:2018-1-4-23-16-20
cronTimerString时间:2018-1-4-23-16-20
定时器里还有:1个任务
1运行:程序
cronTimerString时间:2018-1-4-23-16-30
定时器里还有:1个任务
2运行:程序
cronTimerString时间:2018-1-4-23-16-40
定时器里还有:1个任务
3运行:程序
cronTimerString时间:2018-1-4-23-16-50
定时器里还有:1个任务
4运行:程序
到此,这篇文章就完了!!