【1】java.util.Timer
Timer中主要有两种实现方法:schedule和scheduleAtFixedRate。
① schedule
new Timer("testTimer").schedule(new TimerTask() { @Override public void run() { System.out.println("TimerTask"); } }, 1000,2000);
解释:1000ms是延迟启动时间,2000ms是定时任务周期,每2s执行一次
② scheduleAtFixedRate
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); try { Date date = dateFormat.parse("2019-07-11 12:00:00.000"); new Timer("testTimer1").scheduleAtFixedRate(new TimerTask() { @Override public void run() { System.out.println("TimerTask"); } }, date,2000); } catch (ParseException e) { e.printStackTrace(); }
解释:date是开始时间,2000ms是定时任务周期,每2s执行一次。
Timer中的schedule和scheduleAtFixedRate,前者会等任务结束在开始计算时间间隔,后者是在任务开始就计算时间,有并发的情况
【2】java.util.concurrent.ScheduledExecutorService
【3】SpringTask
① 任务类
@Service public class SpringTask { private static final Logger log = LoggerFactory.getLogger(SpringTask.class); @Scheduled(cron = "1/5 * * * * *") public void task1(){ log.info("springtask 定时任务!"); } @Scheduled(initialDelay = 1000,fixedRate = 1*1000) public void task2(){ log.info("springtask 定时任务!"); } }
② 配置文件修改
1.简单版
<task:annotation-driven/>
2.任务池版
<task:executor id="executor" pool-size="10" /> <task:scheduler id="scheduler" pool-size="10" /> <task:annotation-driven executor="executor" scheduler="scheduler" />
3.解释
假如只有一个定时任务,可以用简单版;如果有多个定时任务,则要用任务池,不然它会顺序执行。
两个任务的时间间隔为:执行时间+设定的定时间隔。
例子:(这个任务8s执行一次)
@Scheduled(cron = "1/4 * * * * *") public void task2(){ log.info("springtask 定时任务2!"); try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } }
关于这个在SpringBoot中同样提供了@Scheduled注解来实现定时任务并做了自动配置,
【4】Quartz
① pom文件配置
<!-- quartz --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> <!--调度器核心包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.4.RELEASE</version> </dependency>
② Job实现
public class HelloWorldJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date()); System.out.println( strTime + ":Hello World!"); } }
③ 调度器(可以用listener在项目启动时执行)
public class MyScheduler { public static void main(String[] args) throws SchedulerException { //创建调度器Schedule SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .build(); //创建触发器Trigger实例(立即执行,每隔1S执行一次) Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) .build(); //开始执行 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
上面用的是简单触发器,也可以用Con触发器,如下:
Trigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity("trigger2", "triggerGroup2") .startNow() .withSchedule(cronSchedule("0 42 10 * * ?")) .build();
④ 整合Spring
也可以直接把上面的调度器写成配置文件,整合spring
配置文件如下:
<bean id="QuarFirstJob" class="com.quartz.QuarFirstJob" /> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="group" value="quartzGroup1" /> <property name="name" value="quartzJob1" /> <!--false表示等上一个任务执行完后再开启新的任务 --> <property name="concurrent" value="false" /> <property name="targetObject"> <ref bean="QuarFirstJob" /> </property> <property name="targetMethod"> <value>first</value> </property> </bean> <!-- 调度触发器 --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="trigger1" /> <property name="group" value="group1" /> <property name="jobDetail"> <ref bean="jobDetail" /> </property> <property name="cronExpression"> <value>0/5 * * * * ?</value> </property> </bean> <!-- 调度工厂 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger" /> </list> </property> </bean>