- Timer实现
- ScheduledExcetor实现
- 使用Quarzt实现
使用java.util.Timer实现调度,功能较单一
(1) Timer实现
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
int i=0;
@Override
public void run() {
System.out.println(i);
i++;
}
},10000,1000);
}
Timer依靠Timer和TimerTask实现定时调度。其中Timer只要实现定义任务的延时时间(delay)和定时调度(period)。TimerTask需要在run方法中实现具体的业务。
Timer实现原理是:一个queue和一个线程。Timer将接受的任务存放于queue中。TimerThread会轮询所有的任务,按照Timer设置的时间休眠和执行任务。
由于Timer基于list实现,一个任务的延迟会影响到后面所有的任务的执行。
(2) ScheduledExcetor实现
- schedule
实现延迟调度,不能实现周期调度
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
System.out.println("begin");
for (int a = 0; a < 10; a++) {
final int count = a;
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println(count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 1, TimeUnit.SECONDS);
}
}
输出结果为:先输出begin,延迟1秒,输出0 1,线程休眠1秒,输出2 3….
- scheduleAtFixedRate(Runnable runnable,long initialDelay,long period,TimeUnit unit)
字面意思可以理解为固定速率调度。不考虑其他因素每过period秒调度一次,基于规定时间进行调度。
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("1");
}
}, 2,2, TimeUnit.SECONDS);
}
- scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)
调度时间取决于每次任务执行的时间长短
(3) Quartz实现
- 单机实现Quartz
单机实现Quartz需要quartz、slf4j、logj等jar的支持。
使用Quartz实现定时调度,需要:Scheduler、Job、以及Trigger
其中Job需要指定执行的任务:JobBuilder.newJob(MyQuarz.class)
Trigger需要指定调度的策略:.withSchedule(builder)
Scheduler将两者组合起来。
public static void main(String[] args){
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDataMap datamap = new JobDataMap();
datamap.put("name","job1");
JobDetail detail = JobBuilder.newJob(MyQuartz.class)
.withIdentity("job1","lin_group")
.setJobData(datamap)
.build();
SimpleScheduleBuilder builder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(100, 5);
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "lin_group")
.startNow()
.withSchedule(builder)
.build();
scheduler.scheduleJob(detail,trigger);
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
具体需要执行的方法:MyQuartz
public class MyQuartz implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Object name = jobExecutionContext.getJobDetail().getJobDataMap().get("name");
System.out.println(name.toString());
}
}
- 配合Spring框架使用
使用配置文件来定义调度策略
1、创建quartz.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="printJobTimer" class="xyz.chanjkf.utils.quarz.PrintJobTimer"/>
<bean id="printJobTimerDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 被调度类:PrintJobTimer -->
<property name="targetObject" ref="printJobTimer"/>
<!-- 被调度方法:print() -->
<property name="targetMethod" value="print"/>
<property name="concurrent" value="false"/>
</bean>
<!-- ======================== 调度触发器 ======================== -->
<bean id="printJobTimerTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="printJobTimerDetail"></property>
<property name="cronExpression">
<value>0 0 */2 * * ?</value>
</property>
</bean>
<!-- ======================== 调度工厂 ======================== -->
<bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="printJobTimerTrigger"/>
</list>
</property>
</bean>
</beans>
2、调度类以及方法:
public class PrintJobTimer {
public void print(){
System.out.println("hello");
}
}
3、在web.xml中声明quartz.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml,classpath:spring-security.xml,classpath:quarz.xml</param-value>
</context-param>
在spring中也可以使用另一种方式创建
@Component("StartupListener")
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
private static boolean isStart = false;
final static DXPLog dxpLog = new DXPLog(StartupListener.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
if(!isStart) {
isStart = true;
startPrint();
}
}
private void startPrint() {
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail detail = JobBuilder
.newJob(PrintJob.class)
.withIdentity("job1", "group1")
.build();
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(10, 1);
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 0 * * ?");
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(simpleScheduleBuilder)
.build();
scheduler.scheduleJob(detail, trigger);
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
下面再记录一下T两种常用Trigger
- SimpleTrigger
SimpleScheduleBuilder builder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(20);
1、repeatSecondlyForever()
每1秒执行一次,直到程序停止
2、repeatSecondlyForever(20);
每20秒执行一次,直到程序停止
3、repeatSecondlyForTotalCount(20);
每1秒执行一次,一共执行20次
4、repeatSecondlyForTotalCount(20, 10)
每10秒执行一次,一共执行20次
- CronTrigger
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 0 * * ?");
1、创建一个每三小时执行的 CronTrigger,且从每小时的整点开始执行:
0 0 0/3 * * ?
2、2005年每天10点15分触发
0 15 10 * * ? 2005
3、每天下午的 2点到2点59分(整点开始,每隔5分触发)
0 0/5 14 * * ?
4、每天下午的 2点到2点59分(整点开始,每隔5分触发) 每天下午的 18点到18点59分
0 0/5 14,18 * * ?
5、从周一到周五每天上午的10点15分触发
0 15 10 ? * MON-FRI
6、每月的第一个中午开始每隔5天触发一次
0 0 12 1/5 * ?
部分内容参考https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/