Timer
只使用一个参数,会在指定的时间后运行,单位毫秒,但是只会执行一次
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("一秒后执行一次");
}
}, 1000);
使用一个参数,单位Date对象,会在指定的日期运行一次
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2022); // 控制年
calendar.set(Calendar.MONTH, 8); // 控制月 这里注意,月份是按国外的月份,8就是9月
calendar.set(Calendar.DAY_OF_MONTH, 4); // 控制日
calendar.set(Calendar.HOUR, 12); // 控制时
calendar.set(Calendar.MINUTE, 0); // 控制分
calendar.set(Calendar.SECOND, 0); // 控制秒
Date time = calendar.getTime(); // 得出执行任务的时间,此处为Thu Sep 05 00:00:00 CST 2022
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("固定年月日执行一次");
}
}, time);
上面使用一个参数只会运行一次程序,我们多数情况下肯定是在每过一定的时间执行一次,比如每过一秒执行一次
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("0毫秒后每过一秒执行一次");
}
}, 0,1000);
也可以使用指定的日期然后每过一秒执行一次
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2022); // 控制年
calendar.set(Calendar.MONTH, 8); // 控制月 这里注意,月份是按国外的月份,8就是9月
calendar.set(Calendar.DAY_OF_MONTH, 4); // 控制日
calendar.set(Calendar.HOUR, 12); // 控制时
calendar.set(Calendar.MINUTE, 0); // 控制分
calendar.set(Calendar.SECOND, 0); // 控制秒
Date time = calendar.getTime(); // 得出执行任务的时间,此处为Thu Sep 05 00:00:00 CST 2022
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("2022年9月4号中午十二点开始执行,每秒执行一次");
}
}, time,1000);
ScheduledExecutorService
使用Timer是单线程的形式,而ScheduledExecutorService是线程池的方式,,这是最理想的定时任务方式
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("使用线程的方式执行,第一个参数是线程,第二个参数是什么时候执行");
}
}, 1, TimeUnit.SECONDS);
当然我们也可以每过指定时间执行一次,比如一秒执行一次
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("使用线程的方式执行,第一个参数是线程,第二个参数是什么时候执行,第三个参数过多久再次执行");
}
}, 0,1,TimeUnit.SECONDS);
Quartz
首先使用quartz不是java自带的包所以需要导入jar包,这里我们使用maven
进行导入
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
然后我们创建一个类实现Job类,在里面写上我们需要执行的定时任务,这里我们编写一个新的类
public class QuertzJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("任务被执行了");
}
}
然后我们在创建一个测试类
public class Quartzmain {
public static void main(String[] args) throws Exception {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建JobDetail实例,并与自己写的Job类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(QuertzJob.class)
.withIdentity("job1", "group1").build();
// 3、构建Trigger实例,每隔1s执行一次
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
.startNow()//立即生效
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)//每隔1s执行一次
.repeatForever()).build();//一直执行
//4、执行
scheduler.scheduleJob(jobDetail, trigger);
System.out.println("--------scheduler start ! ------------");
scheduler.start();
// 当任务执行一分钟后就停止任务
Thread.sleep(1000*60);
scheduler.shutdown();
}
}
cron表达式
public class Quartzmain {
public static void main(String[] args) throws Exception {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建JobDetail实例,并与自己写的Job类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(QuertzJob.class)
.withIdentity("job1", "group1").build();
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1","triggerGroup1")
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("5/6 * * * * ? "))//程序开始五秒后执行一次然后每六秒执行一次
.build();
//4、执行
scheduler.scheduleJob(jobDetail, cronTrigger);
System.out.println("--------scheduler start ! ------------");
scheduler.start();
// 当任务执行一分钟后就停止任务
Thread.sleep(1000*60);
scheduler.shutdown();
}
}
Spring整合Quartz
首先我们创建一个简单的定时任务,测试成功后再尝试使用cron表达式的定时任务
简单的定时任务
第一步导入spring依赖,这里注意,导入的是spring-context-support这个依赖,不要导入成了spring-context
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
然后还要导入tx
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
再导入quart的依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
依赖导入好了就可以开始编写需要执行的定时的任务代码
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("执行任务");
}
}
然后在spring上下文配置定时器的JobDetail和simpleTrigger触发器,最后再绑定即可,这里和没有整合spring是一样的,只不过整合之后是将bean的创建交给spring
<bean id="job" class="spring.MyJob"></bean>
<!-- 2.任务触发器详细信息bean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="spring.MyJob"></property>
</bean>
<!--第二步:2. 定义触发器,并且将jobDetail注入 -->
<bean id="simpleTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<!-- 调度工厂实例化后,经过3秒开始执行调度 -->
<property name="startDelay" value="3000" />
<!-- 每隔2秒执行一次 -->
<property name="repeatInterval" value="2000" />
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<!-- 第三步:配置调度工厂 -->
<bean id="startQuertz" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 管理trigger -->
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
最后直接创建一个测试类启动即可
public class test {
public static void main(String[] args) {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
这里因为不是springboot的项目就只能这样启动,获取上下文配置然后启动
cron表达式的定时任务
首先我们还是依赖都不变,只需要更改xml的配置
<bean id="job" class="spring.MyJob"></bean>
<!-- 2.任务触发器详细信息bean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="spring.MyJob"></property>
</bean>
<!-- 第二种 CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。配置方式如下: -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 4 22 * * ?" />
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<!-- 第三步:配置调度工厂 -->
<bean id="startQuertz" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 管理trigger -->
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
可以看到我们只是将简单的触发器更改成了cron表达式触发器,其他的配置都没有动
spring整合quartz实现方式
这里在第一次创建简单的定时任务时使用的是实现Job接口
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("执行任务");
}
}
当然我们也可以使用继承QuartzJobBean的方式
public class MyJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("任务执行了");
}
}