任务调度.docx
- 文档编号:11931781
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:19
- 大小:306.64KB
任务调度.docx
《任务调度.docx》由会员分享,可在线阅读,更多相关《任务调度.docx(19页珍藏版)》请在冰豆网上搜索。
任务调度
任务调度
从网上发现了好多任务调度的框架,对于小白的编辑来说也很困惑啊,那让我们一起慢慢走近任务调度框架吧!
什么是任务调度
任务调度是操作系统的重要组成部分,而对于实时操作系统,任务调度直接影响其实时性能。
任务调度方式常规可分为:
可打断调度(实时系统基本功能):
关键防止优先级倒置;
不可打断调度:
先来先服务,不可中断。
任务调度算法可分为:
事件驱动调度算法:
根据事件的先后以及任务的优先级安排任务的执行;
时钟驱动调度算法:
一般用于周期任务。
事件驱动调度,依赖外部硬件设备,通过产生中断方式为任务调度提供信号。
分两种:
集成事件驱动调度:
中断的优先级与任务的优先级相对应,中断只有在其优先级高于正在执行的任务时才会被处理器响应。
非集成事件驱动调度:
任务通过外部中断启动,中断优先级与相关任务优先级没有关系。
前言
任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。
本文由浅入深介绍四种任务调度的Java实现:
∙Timer
∙ScheduledExecutor
∙开源工具包Quartz
∙开源工具包JCronTab
Timer
Timer:
是生产者--消费者模型的一种特例:
多生产者,单消费者模型。
优点:
简单易用
缺点:
所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
Java代码测试timer:
Timer测试用例一:
packagecom.zx.scheduler;
importjava.util.Timer;
importjava.util.TimerTask;
publicclassTimerTestextendsTimerTask{
privateStringjobName="";
publicTimerTest(StringjobName){
super();
this.jobName=jobName;
}
@Override
publicvoidrun(){
System.out.println("execute"+jobName);
}
publicstaticvoidmain(String[]args){
Timertimer=newTimer();
longdelay1=1*1000;
longperiod1=1000;
//从现在开始1秒钟之后,每隔1秒钟执行一次job1
timer.schedule(newTimerTest("job1"),delay1,period1);
longdelay2=2*1000;
longperiod2=2000;
//从现在开始2秒钟之后,每隔2秒钟执行一次job2
timer.schedule(newTimerTest("job2"),delay2,period2);
}
}
/**
输出结果:
executejob1
executejob1
executejob2
executejob1
……
*/
Timer测试用例二:
packagecom.zx.scheduler;
importjava.util.Date;
importjava.util.Timer;
importjava.util.TimerTask;
publicclassPlainTimerTaskextendsTimerTask{
@Override
publicvoidrun(){
System.out.println("输出时间:
"+newDate());
}
publicstaticvoidmain(String[]args){
Timertimer=newTimer();
timer.schedule(newPlainTimerTask(),5000L);
}
}
/**
*输出时间:
MonFeb2911:
16:
49CST2016
*/
Timer测试用例三:
packagecom.zx.test;
importjava.util.Timer;
importjava.util.TimerTask;
publicclassTimerTestextendsTimerTask{
staticintflax=0;
@Override
publicvoidrun(){
System.out.println("test"+flax);
flax++;
}
publicstaticvoidmain(String[]args){
Timert=newTimer();
longdelay=1000;
longperiod=10*1000;
t.schedule(newTimerTest(),delay,period);//从现在开始1秒钟之后,每隔10秒钟执行一次
}
}
/**结果
test0
test1
test2
test3
*/
ScheduledExecutor
ScheduledExecutor:
其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。
需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor才会真正启动一个线程,其余时间ScheduledExecutor都是在轮询任务的状态。
Java代码测试ScheduledExecutor
packagecom.zx.scheduler;
importjava.util.concurrent.Executors;
importjava.util.concurrent.ScheduledExecutorService;
importjava.util.concurrent.TimeUnit;
publicclassScheduledExecutorTestimplementsRunnable{
privateStringjobName="";
publicScheduledExecutorTest(StringjobName){
super();
this.jobName=jobName;
}
@Override
publicvoidrun(){
System.out.println("execute"+jobName);
}
publicstaticvoidmain(String[]args){
ScheduledExecutorServiceservice=Executors.newScheduledThreadPool(10);
longinitialDelay1=1;
longperiod1=1;
//从现在开始1秒钟之后,每隔1秒钟执行一次job1
service.scheduleAtFixedRate(
newScheduledExecutorTest("job1"),initialDelay1,
period1,TimeUnit.SECONDS);
longinitialDelay2=1;
longdelay2=1;
//从现在开始2秒钟之后,每隔2秒钟执行一次job2
service.scheduleWithFixedDelay(
newScheduledExecutorTest("job2"),initialDelay2,
delay2,TimeUnit.SECONDS);
}
}
/**
结果:
executejob2
executejob1
executejob1
executejob2
executejob1
executejob2
*/
Calendar
实现复杂任务调度
Java代码测试Calendar
packagecom.zx.scheduler;
importjava.util.Calendar;
importjava.util.Date;
importjava.util.TimerTask;
importjava.util.concurrent.Executors;
importjava.util.concurrent.ScheduledExecutorService;
importjava.util.concurrent.TimeUnit;
publicclassScheduledExceutorTest2extendsTimerTask{
privateStringjobName="";
publicScheduledExceutorTest2(StringjobName){
super();
this.jobName=jobName;
}
@Override
publicvoidrun(){
System.out.println("Date="+newDate()+",execute"+jobName);
}
/**
*计算从当前时间currentDate开始,满足条件dayOfWeek,hourOfDay,
*minuteOfHour,secondOfMinite的最近时间
*@return
*/
publicCalendargetEarliestDate(CalendarcurrentDate,intdayOfWeek,
inthourOfDay,intminuteOfHour,intsecondOfMinite){
//计算当前时间的WEEK_OF_YEAR,DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND等各个字段值
intcurrentWeekOfYear=currentDate.get(Calendar.WEEK_OF_YEAR);
intcurrentDayOfWeek=currentDate.get(Calendar.DAY_OF_WEEK);
intcurrentHour=currentDate.get(Calendar.HOUR_OF_DAY);
intcurrentMinute=currentDate.get(Calendar.MINUTE);
intcurrentSecond=currentDate.get(Calendar.SECOND);
//如果输入条件中的dayOfWeek小于当前日期的dayOfWeek,则WEEK_OF_YEAR需要推迟一周
booleanweekLater=false;
if(dayOfWeek weekLater=true; }elseif(dayOfWeek==currentDayOfWeek){ //当输入条件与当前日期的dayOfWeek相等时,如果输入条件中的 //hourOfDay小于当前日期的 //currentHour,则WEEK_OF_YEAR需要推迟一周 if(hourOfDay weekLater=true; }elseif(hourOfDay==currentHour){ //当输入条件与当前日期的dayOfWeek,hourOfDay相等时, //如果输入条件中的minuteOfHour小于当前日期的 //currentMinute,则WEEK_OF_YEAR需要推迟一周 if(minuteOfHour weekLater=true; }elseif(minuteOfHour==currentSecond){ //当输入条件与当前日期的dayOfWeek,hourOfDay, //minuteOfHour相等时,如果输入条件中的 //secondOfMinite小于当前日期的currentSecond, //则WEEK_OF_YEAR需要推迟一周 if(secondOfMinite weekLater=true; } } } } if(weekLater){ //设置当前日期中的WEEK_OF_YEAR为当前周推迟一周 currentDate.set(Calendar.WEEK_OF_YEAR,currentWeekOfYear+1); } //设置当前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND为输入条件中的值。 currentDate.set(Calendar.DAY_OF_WEEK,dayOfWeek); currentDate.set(Calendar.HOUR_OF_DAY,hourOfDay); currentDate.set(Calendar.MINUTE,minuteOfHour); currentDate.set(Calendar.SECOND,secondOfMinite); returncurrentDate; } publicstaticvoidmain(String[]args)throwsException{ ScheduledExceutorTest2test=newScheduledExceutorTest2("job1"); //获取当前时间 CalendarcurrentDate=Calendar.getInstance(); longcurrentDateLong=currentDate.getTime().getTime(); System.out.println("CurrentDate="+currentDate.getTime().toString()); //计算满足条件的最近一次执行时间 CalendarearliestDate=test .getEarliestDate(currentDate,3,16,38,10); longearliestDateLong=earliestDate.getTime().getTime(); System.out.println("EarliestDate=" +earliestDate.getTime().toString()); //计算从当前时间到最近一次执行时间的时间间隔 longdelay=earliestDateLong-currentDateLong; //计算执行周期为一星期 longperiod=7*24*60*60*1000; ScheduledExecutorServiceservice=Executors.newScheduledThreadPool(10); //从现在开始delay毫秒之后,每隔一星期执行一次job1 service.scheduleAtFixedRate(test,delay,period, TimeUnit.MILLISECONDS); } } /** 输出结果: CurrentDate=WedFeb0217: 32: 01CST2011 EarliestDate=TueFeb816: 38: 10CST2011 Date=TueFeb816: 38: 10CST2011,executejob1 Date=TueFeb1516: 38: 10CST2011,executejob1 */ Quartz Java代码测试quartz packagecom.zx.scheduler; importjava.util.Date; importorg.quartz.Job; importorg.quartz.JobDetail; importorg.quartz.JobExecutionContext; importorg.quartz.JobExecutionException; importorg.quartz.Scheduler; importorg.quartz.SchedulerFactory; importorg.quartz.Trigger; importorg.quartz.helpers.TriggerUtils; publicclassQuartzTestimplementsJob{ @Override //该方法实现需要执行的任务 publicvoidexecute(JobExecutionContextarg0)throwsJobExecutionException{ System.out.println("Generatingreport-"+arg0.getJobDetail().getFullName()+",type="+arg0.getJobDetail().getJobDataMap().get("type")); System.out.println(newDate().toString()); } publicstaticvoidmain(String[]args){ try{ //创建一个Scheduler SchedulerFactoryschedFact= neworg.quartz.impl.StdSchedulerFactory(); Schedulersched=schedFact.getScheduler(); sched.start(); //创建一个JobDetail,指明name,groupname,以及具体的Job类名, //该Job负责定义需要执行任务 JobDetailjobDetail=newJobDetail("myJob","myJobGroup",QuartzTest.class); jobDetail.getJobDataMap().put("type","FULL"); //创建一个每周触发的Trigger,指明星期几几点几分执行 Triggertrigger=TriggerUtils.makeWeeklyTrigger(2,17,47);//注意: 2,17,47表示的是周一17: 47执行任务 trigger.setGroup("myTriggerGroup"); //从当前时间的下一秒开始执行 trigger.setStartTime(TriggerUtils.getEvenSecondDate(newDate())); //指明trigger的name trigger.setName("myTrigger"); //用scheduler将JobDetail与Trigger关联在一起,开始调度任务 sched.scheduleJob(jobDetail,trigger); }catch(Exceptione){ e.printStackTrace(); } } } 结果: 问题及方案: 使用Quartz时需要添加jar包,报此错误,缺少quartz-版本号.jar 例如: quartz-1.5.2.jar 运行后: 报此错误: 缺少commons-logging.jar Quartz整合spring 创建web工程: itcast-quartz Main类 packagecom.itcast.quartz; importorg.springframework.context.support.ClassPathXmlApplicationContext; publicclassMain{ publicstaticvoidmain(String[]args){ newClassPathXmlApplicationContext("classpath: applicationContext-scheduler.xml"); } } MyJob类 packagecom.itcast.quartz; importorg.quartz.JobExecutionContext; importorg.quartz.JobExecutionException; importorg.springframework.context.ApplicationContext; importorg.springframework.scheduling.quartz.QuartzJobBean; publicclassMyJobextendsQuartzJobBean{ @Override protectedvoidexecuteInternal(JobExecutionContextcontext) throwsJobExecutionException{ System.out.println("myJob执行了。 。 。 。 "+context.getTrigger().getKey().getName()); try{ ApplicationContextapplicationContext=(ApplicationContext)context.getJobDetail().getJobDataMap().get("applicationContext"); System.out.println("获取到的spring容器是"+applicationContext); }catch(Exceptione){ System.out.println(e.getMessage()); e.printStackTrace(); System.out.println("出错了"); } } } applicationContext-scheduler.xml xmlversion="1.0"encoding="UTF-8"? > //www.springframework.org/schema/beans" xmlns: context="http: //www.springframework.org/schema/context" xmlns: xsi="http: //www.w3.org/2001/XMLSchema-instance" x
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 任务 调度