jdk实际上自带了两种简单定时任务类,但由于功能的局限性,通知不会应用到项目中,这里只做简单介绍
1.Timer类
1.1概念
java.util.Timer类
Timer可以调用java.util.TimerTask任务
可以使TimerTask按固定频率执行
功能单一,通常不用
1.2任务类
extends TimerTask
public class DemoTimerTask extends TimerTask {
@Override
public void run() {
System.out.println("Timer task1" + new Date());
}
}
1.3启动定时任务
我这里写在了controller,如果要自启动那么定义到main即可
@GetMapping("/timer")
public void timer() {
TimerTask timerTask = new DemoTimerTask();
Timer timer = new Timer();
//指定任务首次执行延迟,执行频率,单位毫秒
timer.schedule(timerTask, 5000, 10000);
}
1.4注意
在多线程情况下Timer运行TimerTask时,
只要其中之一的TimerTask抛出异常,那么所有的TimerTask都会中止
而ScheduledExecutorService解决了这一问题
2.ScheduledExecutorService
2.1概念
java.util.concurrent.ScheduledExecutorService
与Timer类似,也是java自带的定时任务类
区别Timer的地方在于,ScheduledExecutorService是基于线程池设计的,
每个任务都会分配到线程池中的一个线程去执行,并发执行,互不影响
2.2任务类
implements Runnable
public class DemoScheduledExecutorService implements Runnable {
@Override
public void run() {
System.out.println("ScheduledExecutorService task1" + new Date());
}
}
@GetMapping("/scheduledExecutorService")
public void scheduledExecutorService() {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new DemoScheduledExecutorService(),5,10, TimeUnit.SECONDS);
}
//参数说明
1.任务类对象
2.首次执行延迟
3.任务执行频率
4.时间单位TimeUnit
3.SpringTask
1.概念
spring3.x提供的定时任务类,简单好用
2.1开启springtask
如果是一般的spring项目,需要在spring配置文件中开启定时任务
<!--开启定时任务多线程执行-->
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="10"/>
<task:annotation-driven executor="executor" scheduler="scheduler">
<!-- 配置定时任务 -->
<task:scheduled-tasks>
<task:scheduled ref="任务bean1.name" method="任务方法名1" cron="0 * * * * ?" /></task:scheduled-tasks>
<task:scheduled-tasks><task:scheduled ref="任务bean2.name" method="任务方法名2" cron="0 * * * * ?" />
</task:scheduled-tasks>
如果是springboot项目,在启动类上增加注解@EnableScheduling即完成配置,如果需要开启多线程,则要单独编写配置类
@EnableAsync注解表示开启异步执行
@Configuration
@EnableAsync
public class AsyncConfig {
private int corePoolSize = 10;
private int maxPoolSize = 200;
private int queueCapacity = 10;
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.initialize();
return executor;
}
}
2.2任务类
开启springtask后,编写任务类就可以了,spring会自动去bean中扫描注解@Scheduled并标记为任务类
@Component
public class DemoSpringTask {
@Scheduled(cron = "0/5 * * * * ?")
public void demo() {
System.out.println("SpringTask:" + new Date());
}
}
4.Quartz
<!-- Quartz 定时任务-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
@Component
public class DemoQuartzTask1 {
public void soutDate() {
System.out.println("DemoQuartzTask1:" + new Date());
}
}
@Data
public class DemoQuartzTask2 extends QuartzJobBean {
/**
* 这种方式定义任务类可以传参
*/
String name;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println(name + "DemoQuartzTask:" + new Date());
}
}
/**
* MethodInvokingJobDetailFactoryBean
* 指定任务类的bean和bean中的任务方法,但不能传参,适合应用于bean方式定义的任务类
*
* @return MethodInvokingJobDetailFactoryBean
*/
@Bean
MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
bean.setTargetBeanName("demoQuartzTask1");
bean.setTargetMethod("soutDate");
return bean;
}
/**
* JobDetailFactoryBean
* 指定任务类,任务类必须是Job接口的实现类(QuartzJobBean就实现了Job接口)
* 可以传参,通过JobDataMap
*
* @return JobDetailFactoryBean
*/
@Bean
JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(DemoQuartzTask2.class);
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("name", "这是我的名字");
bean.setJobDataMap(jobDataMap);
return bean;
}
/**
* CronTriggerFactoryBean
*/
@Bean
CronTriggerFactoryBean cronTrigger() {
CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
bean.setCronExpression("0/10 * * * * ?");
bean.setJobDetail(jobDetailFactoryBean().getObject());
return bean;
}
/**
* SchedulerFactoryBean
* setTriggers(Trigger... triggers)可变参数,可以给调度器传多个触发器,触发多个任务,调度器内部是线程池调用
*
* @return
*/
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setTriggers(cronTrigger().getObject());
return bean;
}