packagecom.testdemo.pcis.isc.job.king;importjava.text.SimpleDateFormat;importjava.util.UUID;importjava.util.concurrent.Callable;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;importorg.quartz.CronScheduleBuilder;importorg.quartz.JobBuilder;importorg.quartz.JobDetail;importorg.quartz.Scheduler;importorg.quartz.Trigger;importorg.quartz.TriggerBuilder;importorg.quartz.impl.StdSchedulerFactory;/*** 触发器小例子.
* 1. 模拟从数据库中取完整信息,得到cron表达式
* 2. 判断时间是否在inSeconds(10)秒以内需要执行该任务
* 3. 如果在inSeconds(10)秒以内,从线程池中启动新线程,发送数据
*@authorKing
* @time 2016/07/07*/
public classMyTrigger {//指定任务处于inSeconds秒内时,就开启新线程任务
private static final int inSeconds = 10;//秒//时间格式化器
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");//线程池
private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);public static void main(String[] args) throwsException {//模拟从数据库中取到一个与计划相关完整单行信息
Object dataFromDb = newObject();//模拟dataFromDb该行信息中cron表达式如下
String cronArg = "50 45 14 * * ?";//得到计划scheduler
Scheduler scheduler = newStdSchedulerFactory().getScheduler();//创建工作任务job
JobDetail job = JobBuilder.newJob().ofType(MyJob.class)
.withIdentity("job1", "group1").build();//创建触发器trigger//如果cronArg表达式不正确,会报java.text.ParseException,可以用来判断前台页面插入的cron表达式是否合法
Trigger trigger =TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1").startNow()//.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(10,2))
.withSchedule(CronScheduleBuilder.cronSchedule(cronArg))//.withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInHours(2))
.build();//对该计划指定运行 的工作任务和触发器,该行一定要有,不然触发器的下次执行时间会为null
scheduler.scheduleJob(job, trigger);//开始计划的执行,但这里最终目的只需要得到下次执行时间,而不需要真正执行,不然会启动线程增加性能消耗//s.start();//判断触发器trigger的下次执行时间是否临近
boolean flag =nearToRun(trigger);//如果临近,那么开启新线程
if(flag){
startNewThread(trigger,dataFromDb);
}//关闭计划scheduler//s.shutdown(true);
}/*** 判断触发器trigger的下次执行时间是否临近inSeconds秒以内(目前为10秒以内)
*@paramtrigger
*@return
*/
public static booleannearToRun(Trigger trigger){//打印下次执行时间,得到结果
System.out.println("trigger下次触发时间:" +sdf.format(trigger.getNextFireTime()));//获取时差 = 该任务下次执行时间 - 当前时间
long delayTimeMillis = trigger.getNextFireTime().getTime() -System.currentTimeMillis();//如果 0秒
if (delayTimeMillis > 0 && delayTimeMillis < inSeconds * 1000) {return true;
}else{return false;
}
}/*** 从线程池开启新线程
*@paramtrigger 触发器
*@paramdataFromDb 从数据库中取到的单行完整信息
*@throwsException*/
public static void startNewThread(Trigger trigger,Object dataFromDb) throwsException{//模拟从数据库中取到的数据dataInDb
UUID uuid =UUID.randomUUID();
Callable call = newMyCallableImpl(uuid.toString(),dataFromDb);//再次获取时差,因为离executor.schedule(arg...)越近,越精确
long delayTimeMillis2 = trigger.getNextFireTime().getTime() -System.currentTimeMillis();
Future future=executor.schedule(call, delayTimeMillis2,TimeUnit.MILLISECONDS);//如果1 * 3600 * 1000 = 1小时内还得不到返回信息就会报java.util.concurrent.TimeoutException,该参数从dataFromDb中提取
String result = (String) future.get( 1 * 3600 * 1000,TimeUnit.MILLISECONDS);
System.out.println("刚才启动的线程结束了,返回信息为:" +result);
}
}