一、前言
在实际开发中,会经常定时更新一些数据,小到Java项目中的collection,大到数据库表格。又比如定时给客户发送email;又比如说交易所行情数据每天存储完成后,需要根据历史数据进行筛选新的开仓数据作为条件定时存储到其他数据库中。
二、Java自带的简单任务调用类
(一)、Timer
1、Timer实现任务调度的核心类是Timer和TimerTask
1)、创建一个TimerTask的子类,实现自己的run方法(自定义所要调度的任务);
2)、Timer负责设定TimerTask相对于当前多长时间执行此任务和执行任务的间隔。
2、原理:Timer将接受的任务丢到自己的TaskList中,TaskList按照Task的最初执行时间进行排列。
3、缺点:所有任务都是由一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务执行,前一个任务的延迟会影响到之后的任务。
4、简单代码:
public class TimerTest extends TimerTask { private String jobName=""; public TimerTest(String jobName) { super(); this.jobName=jobName; } @Override public void run() { System.out.println("excute :"+ jobName); } public static void main(String[] args) { Timer timer = new Timer(); long delay1 = 1*1000; long peroid1 = 1000; // 从现在开始过1秒钟之后,每隔1秒钟执行一次job1(schedule:预定计划) timer.schedule(new TimerTest("job1"), delay1,peroid1); long delay2 = 2*1000; long peroid2 = 2000; // 从现在开始过2秒钟之后,每隔2秒钟执行一次job2 timer.schedule(new TimerTest("-----job2"), delay2, peroid2); } }
(二)、ScheduleExecutor任务安排器
1、鉴于Timer的缺陷,Java5推出了基于线程池设计的ScheduleExecutor.每个被调度的任务,都对应开启了一个线程,因此任务并发执行,相互之间不受影响;
2、当任务执行时间带来时候,任务安排器ScheduleExecutor才会真正的启动一个线程,其余时间ScheduleExecutor都在轮询任务状态。
3、代码:
public class ScheduleExecutor implements Runnable { private String jobName = ""; public ScheduleExecutor(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 initialDelay1 = 1; long period1 = 1; // 从现在开始1秒之后,每隔1一秒钟执行一次job1 service.scheduleAtFixedRate(new ScheduleExecutor("job1"), initialDelay1, period1, TimeUnit.SECONDS); long initialDelay2 = 2; long period2 = 2; // 从现在开始2秒之后,每隔2秒钟执行一次job2 service.scheduleAtFixedRate(new ScheduleExecutor("----job2"), initialDelay2, period2, TimeUnit.SECONDS); } }
三、开源工具包Quartz和JCrontab
(一)、Quartz
1、创建具体事件执行接口,Dothings.java,其两个子类DoingA.java、DoingB.java(只是打印两句话)
public static void doA() { SimpleDateFormat form