您的位置:首页 > 编程语言 > Java开发

全面解析JAVA中的任务调度机制

2015-10-28 21:31 453 查看
任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。JAVA中的任务调度主要包含以下3种:1、Timer2、ScheduledExecuror3、开源工具包Quartz一、Timer java.util.Timer是一种最简单的任务调度机制,使用Timer 实现任务调度的核心类是 Timer 和 TimerTask。其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的run 方法,然后将其丢给 Timer 去执行即可。Timer的设计核心是一个 TaskList 和一个 TaskThread。Timer 将接收到的任务丢到自己的 TaskList中,TaskList 按照 Task 的最初执行时间进行排序。TimerThread在创建 Timer 时会启动成为一个守护线程。这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。Timer的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。例子:
package com.lza.taskSchedule;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest extends TimerTask{
private String jobName="";
public TimerTest(String jobName){
super();
this.jobName=jobName;
}
@Override
public void run(){//覆写执行方法
System.out.println("execute "+jobName+new Date());
}
public static void main(String[] args){
Timer timer=new Timer();
long delay1=1*1000;
long period1=1000;
timer.schedule(new TimerTest("Job1"),delay1,period1);//从现在开始 1 秒后 每隔1秒 执行1次Job1
long delay2=2*1000;
long period2=2000;
timer.schedule(new TimerTest("Job2"),delay2,period2);//从现在开始 2 秒后 每隔2秒 执行1次Job2
}
}
二、ScheduledExecutorScheduledExecutor的设计思想是:每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。 ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay,initialDelay+period, initialDelay+2*period, …; ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay,  initialDelay+2*executeTime+2*delay。ScheduleAtFixedRate 是基于固定时间间隔进行任务调度, ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。例子:
package com.lza.taskSchedule;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest implements Runnable {
private String jobName = "";

public ScheduledExecutorTest(String jobName) {
super();
this.jobName = jobName;
}

@Override
public void run() {
System.out.println("execute " + jobName);
}

public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

long delayTime = 1;
long period = 1;
// 从现在开始1秒钟之后,每隔1秒钟执行一次job1
service.scheduleAtFixedRate(//固定时间间隔
new ScheduledExecutorTest("job1"), delayTime,
period, TimeUnit.SECONDS);

long delayTime2 = 2;
long period2 = 2;
// 从现在开始2秒钟之后,每隔2秒钟执行一次job2
service.scheduleWithFixedDelay(//不固定时间间隔
new ScheduledExecutorTest("job2"), delayTime2,
period2, TimeUnit.SECONDS);
}
}
三、开源工具包QuartzQuartz是一个强大的开源定时调度器,它主要由四部分构成:1、Job 表示工作也就是具体要执行的内容接口,这个接口只有一个方法void execute(JobExecutionContext context)2、JobDetail 表示一个具体的可执行的调度程序,而Job就是这个可执行调度程序所要执行的内容。另外JobDetail还包含了这个任务调度的方案和策略。3、Trigger 触发器 用来定义任务调度的时间与间隔、频率等。4、Scheduler 代表一个调度容器,一个调度容器可以注册多个JobDetail和Trigger。然后将它们组合在一起就可以用Scheduler容器进行调度了。整个Quartz的工作原理就是通过Scheduler这个容器去存储众多的JobDetail和Trigger,当容器启动后,由Trigger自动触发 去执行相应的JobDetailJobDetail本身就是一个可以执行的工作,Trigger则控制系统什么时候 按什么策略去调用JobDetail执行,而Scheduler的作用只是把它们两个组装在一起。在Scheduler这个容器中,通过线程池去对各个Job进行并行调度,提高容器的工作效率。例子:
package com.lza.taskSchedule;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 构建一个Job类  这个类就是任务具体执行的操作类
* @author Administrator
*
*/
public class TimerJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("Generating report - "
+ context.getJobDetail().getFullName() + ", "
+ context.getJobDetail().getJobDataMap().get("name")
+ context.getJobDetail().getJobDataMap().get("age"));
System.out.println(new Date().toString());
}

}
package com.lza.taskSchedule;
import java.util.Map;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzManager {
private  Scheduler scheduler;
private final static String JOB_GROUP_NAME="TestJob";
private final static String TRIGGER_GROUP_NAME="TestTrigger";
private static QuartzManager instance = new QuartzManager();

public static QuartzManager getInstance(){
return instance;
}
public  void init( ){
try {
scheduler=new StdSchedulerFactory().getScheduler();
scheduler.start();
} catch (SchedulerException e) {
System.out.println("schedule start fail:"+e);
}

}
public QuartzManager(){
init();
}
public   boolean  addJob(String jobName, String jobClass, String time ,Map<Object,Object> params) {
boolean result = false;
try {

JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, Class.forName(jobClass));// 任务名,任务组,任务执行类
jobDetail.getJobDataMap().putAll(params);
// 触发器
CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
trigger.setCronExpression(time);// 触发器时间设定
if(scheduler.isShutdown()){
init( );
}
scheduler.scheduleJob(jobDetail, trigger);

result = true;
} catch (Exception e) {
result = false;
System.out.println("schedule addJob fail jobName = " + jobName + ". time = " + time + ". jobClass = " + jobClass);
}
return result;
}
}
package com.lza.taskSchedule;

import java.util.HashMap;
import java.util.Map;
public class QuartzTest {
public static void main(String args[]){
//TestJob testJob=new TestJob("Hello",21);
Map<String,Object> testMap=new HashMap<String,Object>();
testMap.put("name", "Hello");
testMap.put("age", 21);
boolean result=QuartzManager.getInstance().addJob("testId",TimerJob.class.getName() ,"0 36 15 28 10 ?", (Map)testMap);
System.out.println(result);
}
}
参考链接:https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/
http://lavasoft.blog.51cto.com/62575/181907/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  任务调度 quartz