java中可以实现任务调度的几种方式总结
任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。
(1)Timmer
使用 Timer 实现任务调度的核心类是 Timer 和 TimerTask。其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的 run 方法,然后将其丢给 Timer 去执行即可。
Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
以下为Timmer类的简单例子:
public class test {
public static void main(String[] args) {
final SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timer timer = new Timer();
// 从当前时间之后10秒开始执行,每2秒执行一次
timer.schedule(new TimerTask() {
@Override
public void run() {
String timeString=df.format(new Date());
System.out.println(" "+timeString+ " so easy......");
}
}, new Date(System.currentTimeMillis() + 10000), 2000);
}
}
执行结果:
(2)ScheduledExecutor
ScheduledExecutor是基于线程池设计的。
其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。
public class test {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
/**
* 任务1
*/
long initialDelay1 = 6;
long period1 = 2;
// 从现在开始6秒钟之后,每隔2秒钟执行一次job1
service.scheduleAtFixedRate(new MyRunnable("我的定时任务111啊"), initialDelay1,
period1, TimeUnit.SECONDS);
/**
* 任务2
*/
long initialDelay2 = 2;
long period2 = 1;
// 从现在开始6秒钟之后,每隔2秒钟执行一次job1
service.scheduleAtFixedRate(new MyRunnable("我的定时任务222啊"), initialDelay2,
period2, TimeUnit.SECONDS);
}
}
class MyRunnable implements Runnable {
private String JobName;
public MyRunnable() {
}
public MyRunnable(String JobName) {
this.JobName = JobName;
}
@Override
public void run() {
System.out.println("正在执行----" + this.JobName);
}
}
(3)开源工具包 Quartz
Quartz的核心元素:
Scheduler:任务调度器,所有的任务都是从这里开始。
Trigger:触发器,定义任务执行的方式、间隔。
JobDetail & Job : 定义任务具体执行的逻辑。
案例:没个1分钟执行一次,共两个Job。执行结果如图:
主代码:
public class MyCreateXml {
public static void main(String args[]) throws Exception {
run();
}
public static void run() throws Exception {
System.out.println("------- 初始化Scheduler ---------");
StdSchedulerFactory sf = new StdSchedulerFactory();
// quartz的schedulerFactory实现解析。SchedulerFactory是一个接口,用于Scheduler的创建和管理。
Properties props = new Properties();
props.put("org.quartz.scheduler.instanceName", "MyScheduler");// 调度器属性
props.put("org.quartz.threadPool.threadCount", "2");// 线程配置,线程池的数量
sf.initialize(props);// 初始化
Scheduler sched = sf.getScheduler();
System.out.println("------- 初始化Scheduler完成 --------");
System.out.println("------- Jobs配置 ----------------");
JobDetail job1 = newJob(MyJob1.class).withIdentity("myJob-1",
"my-job-1").build();
JobDetail job2 = newJob(MyJob2.class).withIdentity("myJob-2",
"my-job-2").build();
CronTrigger trigger1 = newTrigger()
.withIdentity("triggerForMe1", "my-trigger1")
.withSchedule(cronSchedule("0 0/1 * * * ?")).build();// 这是一个触发器,每隔1分钟触发一次
CronTrigger trigger2 = newTrigger()
.withIdentity("triggerForMe2", "my-trigger2")
.withSchedule(cronSchedule("0 0/1 * * * ?")).build();
job1.getJobDataMap().put("MyName", "小兔子");
job2.getJobDataMap().put("MyName", "小猪猪");
Date scheduleTime1 = sched.scheduleJob(job1, trigger1);// 触发器trigger1,触发job1。
Date scheduleTime2 = sched.scheduleJob(job2, trigger2);
System.out.println(job1.getKey() + " has been scheduled to run at: "
+ scheduleTime1 + " and repeat based on expression: "
+ trigger1.getCronExpression());
System.out.println(job2.getKey() + " has been scheduled to run at: "
+ scheduleTime2 + " and repeat based on expression: "
+ trigger2.getCronExpression());
System.out.println("------- 开启任务调度器------");
sched.start();
System.out.println("------- 任务调度器已经开启 ------");
}
}
两个Job:
public class MyJob1 implements Job{
private String MyName;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
MyName = data.getString("MyName");
System.err.println( MyName+" 啊,你长得真好看!!!");
}
public String getMyName() {
return MyName;
}
public void setMyName(String myName) {
MyName = myName;
}
}
public class MyJob2 implements Job{
private String MyName;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap data = context.getJobDetail().getJobDataMap();
MyName = data.getString("MyName");
System.err.println( MyName+" 啊,你长得也好看!!!");
}
public String getMyName() {
return MyName;
}
public void setMyName(String myName) {
MyName = myName;
}
}