通常的系统都会有一些定时任务,那么咱们将这个定时任务封装起来,只要系统须要添加定时任务时,只需调用此方法传入所须要的值便可完成定时任务。 本身自学整理的一些随笔java
1.首先对周期粒度进行封装数组
public enum GranularityPeriod{ UNSPECIFIED(0), ONE_MIN(1), TWO_MINS(2), THREE_MINS(3), FOUR_MINS(4), FIVE_MINS(5), SIX_MINS(6), TEN_MINS(10), TWELVE_MINS( 12), FIFTEEN_MINS(15), TWENTY_MINS(20), THIRTY_MINS(30), ONE_HOUR(60), TWO_HOURS(120), THREE_HOURS(180), FOUR_HOURS( 240), SIX_HOURS(360), EIGHT_HOURS(480), TWELVE_HOURS(720), TWENTY_FOUR_HOURS(1440); private final int value; GranularityPeriod(int value) { this.value = value; } public int value() { return this.value; } public static GranularityPeriod getGranularityPeriod(int value) { switch (value) { case 0: return UNSPECIFIED; case 1: return ONE_MIN; case 2: return TWO_MINS; case 3: return THREE_MINS; case 4: return FOUR_MINS; case 5: return FIVE_MINS; case 6: return SIX_MINS; case 10: return TEN_MINS; case 12: return TWELVE_MINS; case 15: return FIFTEEN_MINS; case 20: return TWENTY_MINS; case 30: return THIRTY_MINS; case 60: return ONE_HOUR; case 120: return TWO_HOURS; case 180: return THREE_HOURS; case 240: return FOUR_HOURS; case 360: return SIX_HOURS; case 480: return EIGHT_HOURS; case 720: return TWELVE_HOURS; case 1440: return TWENTY_FOUR_HOURS; } throw new IllegalArgumentException("NOT GranularityPeriod matched the argument!"); } }
2.对同步方式进行封装app
public enum DateCycle { BY_DAY, BY_WEEK, BY_MONTH; }
public class DayOfWeek { public static String getDay(int i) { switch (i) { case 0: return "Sun"; case 1: return "Mon"; case 2: return "Tue"; case 3: return "Wed"; case 4: return "Thu"; case 5: return "Fri"; case 6: return "Sat"; } throw new IllegalArgumentException("NOT day matched the argument!"); } }
3.设置须要定时同步的周期对象ide
(1)同步任务的任务名 跟 任务组名进行封装测试
public class JobInfo { private String jobName; private String jobGroupName; public JobInfo(String jobName,String jobGroupName){ this.jobName = jobName; this.jobGroupName = jobGroupName; } public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroupName() { return jobGroupName; } public void setJobGroupName(String jobGroupName) { this.jobGroupName = jobGroupName; } }
(2)定时任务的对象设定,并指定任务名 任务组名ui
import java.io.Serializable; import java.util.HashMap; import java.util.Map; public class TimingSync implements Serializable { private static final long serialVersionUID = 1L; public static final Integer SWTICH_OFF =0; public static final Integer BY_DAY =1; public static final Integer BY_WEEK =2; public static final Integer BY_MONTH =3; public static final Integer TYPE_IOPS =0; //public static final String IOPS_JOB_NAME ="my_sync"; //public static final String IOPS_JOB_GROUPNAME ="my_group"; /** * 0--- 定时同步开关关闭 * 1--- 按天定时 * 2--- 按周定时 * 3--- 按月定时 */ private Integer status; private String day;//按月定时时填写该字段从1开始,第0位表明第一天,如1110101 表明某月的1号,2号,3号,5号,7号 private String week;//按周定时时填写该字段从周日开始一共7位0000000,如0100001 表明周一和周六 private Integer businessType;// 定时任务的业务类型,0表明my_sync,能够扩展其余业务 private String synctime = "00:00:00"; public final static Map<Integer,EbsJobInfo> JOB_TYPE_NAME_MAP = new HashMap<Integer,JobInfo>(); static { JOB_TYPE_NAME_MAP.put(TYPE_MY, new EbsJobInfo("my_sync", "my_group")); } public String getWeek() { return week; } public void setWeek(String week) { this.week = week; } public String getDay() { return day; } public void setDay(String day) { this.day = day; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getSynctime() { return synctime; } public void setSynctime(String synctime) { this.synctime = synctime; } @Override public String toString() { return "TimingSync [businessType="+businessType+", status=" + status + ", week=" + week + ", day=" + day + ", synctime=" + synctime + "]"; } public Integer getBusinessType() { return businessType; } public void setBusinessType(Integer businessType) { this.businessType = businessType; } }
4.封装调度机信息,用于存储所须要的同步周期方式this
public class ScheduleInfo implements Serializable, Cloneable { private static final long serialVersionUID = 3258130271374160953L; private String quartzName; private String quartzGroup; private String executorId; private Date startTime; private Date endTime; private Date tiggerTime; private String weekDays, monthDays; private DateCycle dateCycle = DateCycle.BY_DAY; public String getWeekDays() { return weekDays; } public void setWeekDays(String weekDays) { this.weekDays = weekDays; } public String getMonthDays() { return monthDays; } public void setMonthDays(String monthDays) { this.monthDays = monthDays; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public String getExecutorId() { return executorId; } public void setExecutorId(String executorId) { this.executorId = executorId; } public String getQuartzGroup() { return quartzGroup; } public void setQuartzGroup(String quartzGroup) { this.quartzGroup = quartzGroup; } public String getQuartzName() { return quartzName; } public void setQuartzName(String quartzName) { this.quartzName = quartzName; } private GranularityPeriod granularityPeriod = GranularityPeriod.ONE_MIN; public static ScheduleInfo newInstance(Date startTime, Date stopTime) { ScheduleInfo schedule = new ScheduleInfo(); schedule.startTime = startTime; schedule.endTime = stopTime; return schedule; } public Date getTiggerTime() { return tiggerTime; } public void setTiggerTime(Date tiggerTime) { this.tiggerTime = tiggerTime; } public Object clone() throws CloneNotSupportedException { ScheduleInfo clone = (ScheduleInfo) super.clone(); if(null == this.startTime){ clone.startTime = null; } else{ clone.startTime = (Date) this.startTime.clone(); } if(null == this.endTime){ this.endTime = null; } else{ clone.endTime = (Date) this.endTime.clone(); } return clone; } public GranularityPeriod getGranularityPeriod() { return granularityPeriod; } public void setGranularityPeriod(GranularityPeriod granularityPeriod) { this.granularityPeriod = granularityPeriod; } public DateCycle getDateCycle() { return dateCycle; } public void setDateCycle(DateCycle dateCycle) { this.dateCycle = dateCycle; } }
5.封装方法生成设定的所指望的同步规则spa
public class CronTriggerUtil { // 所须要的符号 /** * Comment for <code>SPACE</code> */ public final static String SPACE = " "; /** * Comment for <code>ZERO</code> */ public final static String ZERO = "0"; /** * Comment for <code>SUB</code> */ public final static String SUB = "-"; /** * Comment for <code>DIV</code> */ public final static String DIV = "/"; /** * Comment for <code>ASTERISK</code> */ public final static String ASTERISK = "*"; /** * Comment for <code>INTERROGATION</code> */ public final static String INTERROGATION = "?"; /** * Comment for <code>COMMA</code> */ public final static String COMMA = ","; /** * 根据传入的自定义的定时方式生成trigger所认识的定时任务规则 * */ public String toCronExpr(ScheduleInfo schedule) { String expr = toTimeCronExpr(schedule) + toDateCronExpr(schedule); return expr; } /** * 得到时间表达式,分为3中状况处理,分别是:没有时间段,有一个时间段,有多个时间段, */ private String toTimeCronExpr(ScheduleInfo schedule) { StringBuilder result = new StringBuilder(); // 用开始时间做为启动时间 Date date = schedule.getStartTime(); Date currentDate = new Date(System.currentTimeMillis()); if(date == null){ date = currentDate; } int setSecond = getStartSeconds(date); if(setSecond < 59){//59+1的话会致使开始时间大于触发时间,定时任务会延迟一个周期触发,因此这里去掉59s时的加1操做 setSecond = setSecond+1; } if(setSecond == 60){ setSecond = 0; } result.append(setSecond).append(SPACE); // 特殊处理,在周期为天,判断tiggerTime。24小时 if(schedule.getGranularityPeriod().value() == 1440){ // date = new Date(date.getTime() + 1000 * 60 * 60); result.append(getStartMinute(date)).append(SPACE).append(getStartHour(date)).append(SPACE); } // 特殊处理,在周期为天,判断tiggerTime。12小时 else if(schedule.getGranularityPeriod().value() == 720){ // date = new Date(date.getTime() + 1000 * 60 * 60); result.append(getStartMinute(date)).append(SPACE); if(schedule.getEndTime() != null && schedule.getEndTime().getTime() - date.getTime() < 43200000){ result.append(getStartHour(date)).append(SPACE); } else{ result.append(getStartHour(date) + COMMA + getEndHour(date)).append(SPACE); } } // 当即执行的状况 else if(schedule.getGranularityPeriod().value() == 0){ date = new Date(date.getTime() + 1000 * 60); result.append(getStartMinute(date)).append(SPACE).append(getStartHour(date)).append(SPACE); } // 普通状况 else{ result.append(0).append(DIV).append(getValue(schedule.getGranularityPeriod())).append(SPACE) .append(getHourTime(schedule)).append(SPACE); } return result.toString(); } /** * trigger time return start Seconds */ private int getStartSeconds(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.SECOND); } /** * trigger time return start miniute */ private int getStartMinute(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.MINUTE); } /** * trigger time return start hour */ private int getStartHour(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.HOUR_OF_DAY); } /** * 得到日期的月数 */ private int getMonth(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.MONTH) + 1; } /** * 得到日期的年数 */ private int getYear(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.YEAR); } /** * 得到日期的天数 */ private int getDay(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); return cal.get(Calendar.DAY_OF_MONTH); } /** * 获取12小时的结束时间 * * @param startHour * @return */ private int getEndHour(Date date) { Calendar cal = new GregorianCalendar(); cal.setTimeInMillis(date.getTime()); int hour = cal.get(Calendar.HOUR_OF_DAY); if(hour < 12){ return 12 + hour; } return (12 + hour) % 24; } /** * 获得循环周期为月的具体的号数,假如输入的是1,那么就加入他所在位置的号数 * exp: input = "111110001001" output= "1,2,3,4,5,9,12"; */ private Object getByMonthDays(ScheduleInfo schedule) { String days = schedule.getMonthDays(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < days.length(); i++){ if("1".equals(days.charAt(i) + "")){ builder.append(i + 1).append(COMMA); } } String temp = builder.toString(); if(temp.endsWith(COMMA)){ return temp.substring(0, temp.length() - 1); } return temp; } /** * 获得循环周期为周的具体的星期天数, 例如输入的是1, * 那么就加入他所在位置的星期数 exp: input = "0001000"; output= "Wed"; */ public String getByWeekDays(ScheduleInfo schedule) { String days = schedule.getWeekDays(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < days.length(); i++){ if("1".equals(days.charAt(i) + "")){ builder.append(DayOfWeek.getDay(i)).append(COMMA); } } String temp = builder.toString(); if(temp.endsWith(COMMA)){ return temp.substring(0, temp.length() - 1); } return temp; } private String toDateCronExpr(ScheduleInfo schedule) { StringBuilder result = new StringBuilder(); if(schedule.getGranularityPeriod().value() == 0){ Date date = schedule.getStartTime(); if(date == null) date = new Date(System.currentTimeMillis()); result.append(getDay(date)).append(SPACE).append(getMonth(date)).append(SPACE).append(INTERROGATION) .append(SPACE).append(getYear(date)); } else if("BY_DAY".equals(schedule.getDateCycle().toString())){ result.append(ASTERISK).append(SPACE).append(ASTERISK).append(SPACE).append(INTERROGATION); } else if("BY_WEEK".equals(schedule.getDateCycle().toString())){ result.append(INTERROGATION).append(SPACE).append(ASTERISK).append(SPACE).append(getByWeekDays(schedule)); } else if("BY_MONTH".equals(schedule.getDateCycle().toString())){ result.append(getByMonthDays(schedule)).append(SPACE).append(ASTERISK).append(SPACE).append(INTERROGATION); } return result.toString(); } /** * 因为跨多个小时quartz不认,最大只能以小时为单位,因此只能对其进行转换。 * 如:0 0/240 * * ? 想以天天为单位,每隔4个小时触发一次,但状况仍是每一个小时触发一次。 只有将其改成 0 0/60 * 0,4,8,12,16,20 */ public String getHourTime(ScheduleInfo schedule) { int hourUnit = schedule.getGranularityPeriod().value(); String builder = null; if(hourUnit == 120){ builder = "0,2,4,6,8,10,12,14,16,18,20,22"; } else if(hourUnit == 180){ builder = "0,3,6,9,12,15,18,21"; } else if(hourUnit == 240){ builder = "0,4,8,12,16,20"; } else if(hourUnit == 360){ builder = "0,6,12,18"; } else if(hourUnit == 480){ builder = "0,8,16"; } else if(hourUnit == 720){ builder = "0,12"; }else{ builder = "*"; } return builder; } /** * 因为quartz的表达式最大支持为60分钟,所以,大于60就看成是60 */ public String getValue(GranularityPeriod value) { if(value.value() > 60){ return "60"; } return value.value() + ""; } }
6.设置定时任务(定时时间所要执行的任务)code
public class QuartzJob implements Job{ @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { for(int i = 0; i < 5;i = i + 1){ for(int j = 0; j < 3; j++){ System.out.println("数组中的平均值"+j); } System.out.println("1111111"); } } }
7.将定时任务添加到JobDetail中对象
public class QuartzManager { private static SchedulerFactory schedulerFactory = new StdSchedulerFactory(); /** * @Description: 添加一个定时任务 * * @param jobName 任务名 * @param jobGroupName 任务组名 * @param triggerName 触发器名 * @param triggerGroupName 触发器组名 * @param jobClass 任务 * @param cron 时间设置,参考quartz说明文档 */ @SuppressWarnings({ "rawtypes" }) public static void addJob(String jobName, String jobGroupName, Class jobClass, ScheduleInfo scheduleInfo) { try { //调度器 Scheduler sched = schedulerFactory.getScheduler(); // 任务名,任务组,任务执行类 JobDetail jobDetail= new JobDetail(jobName,jobGroupName,jobClass); // 建立Trigger对象 触发器 CronTrigger cronTrigger = new CronTrigger(jobName,jobGroupName); cronTrigger.setStartTime(scheduleInfo.getStartTime()); cronTrigger.setCronExpression(new CronTriggerUtil().toCronExpr(scheduleInfo)); cronTrigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING); sched.scheduleJob(jobDetail, cronTrigger); // 启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { } } /** * @Description: 开始一个定时任务 */ public static void startTimingJob(Integer jobType){ UDCTimingSync timeSyncObj = new UDCTimingSync(); timeSyncObj.setStatus(1); timeSyncObj.setSynctime("20:57:00"); ScheduleInfo schedule_info = new ScheduleInfo(); if(null == timeSyncObj.getStatus()){ return; } if(timeSyncObj.getStatus().equals(UDCTimingSync.SWTICH_OFF)){ return; } if(timeSyncObj.getStatus().equals(UDCTimingSync.BY_DAY)){//按天 schedule_info.setDateCycle(DateCycle.BY_DAY); schedule_info.setGranularityPeriod(GranularityPeriod.TWENTY_FOUR_HOURS); schedule_info.setStartTime(QuartzManager.getStartTime(timeSyncObj.getSynctime())); }else if(timeSyncObj.getStatus().equals(UDCTimingSync.BY_WEEK)){//按周 schedule_info.setDateCycle(DateCycle.BY_WEEK); schedule_info.setWeekDays(timeSyncObj.getWeek().toString()); schedule_info.setGranularityPeriod(GranularityPeriod.TWENTY_FOUR_HOURS); schedule_info.setStartTime(QuartzManager.getStartTime(timeSyncObj.getSynctime())); }else if(timeSyncObj.getStatus().equals(UDCTimingSync.BY_MONTH)){ schedule_info.setDateCycle(DateCycle.BY_MONTH); schedule_info.setMonthDays(timeSyncObj.getDay().toString()); schedule_info.setGranularityPeriod(GranularityPeriod.TWENTY_FOUR_HOURS); schedule_info.setStartTime(QuartzManager.getStartTime(timeSyncObj.getSynctime())); } QuartzManager.addJob(UDCTimingSync.JOB_TYPE_NAME_MAP.get(jobType).getJobName(), UDCTimingSync.JOB_TYPE_NAME_MAP.get(jobType).getJobGroupName(), QuartzJob.class, schedule_info); } /** * @Description: 将传入的时间转成日历标准时间 */ public static Date getStartTime(String limitBeginTime) { Calendar calendar = Calendar.getInstance(); // 获取当前时间 Date currentDate = new Date(System.currentTimeMillis()); calendar.setTime(currentDate); Date now = calendar.getTime(); String[] begins = limitBeginTime.split(":"); calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(begins[0])); calendar.set(Calendar.MINUTE, Integer.parseInt(begins[1])); calendar.set(Calendar.SECOND, Integer.parseInt(begins[2])); Date beginTime = calendar.getTime(); // 当开始时间小于或者等于当前时间,则将日期增长一天 boolean isGreater = beginTime.after(now); if (!isGreater) { calendar.add(Calendar.DAY_OF_MONTH, 1); } return calendar.getTime(); } }
8.测试类 调用定时任务
public class QuartzTest { public static void main(String[] args) { initJobs(); } /** * @Description: 调用定时任务组,传入定时任务组名 */
private static void initJobs(){ QuartzManager.startTimingJob(UDCTimingSync.TYPE_IOPS); System.out.print("now time is"+new Date(System.currentTimeMillis())); } }