美文网首页
java定时任务

java定时任务

作者: 丰极 | 来源:发表于2018-09-28 16:15 被阅读0次

    Java开发过程中经常会遇到使用定时任务的情况,我总结了一下有如下四种方式:Timer、ScheduledExecutorService、SpringTask、Quartz。

    一、使用java的Timer

    1、Timer

    new Timer("testTimer").schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("TimerTask");
                }
            }, 1000,2000);
    

    解释:1000ms是延迟启动时间,2000ms是定时任务周期,每2s执行一次

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    try {
        Date date = dateFormat.parse("2018-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有2中方法schedule和scheduleAtFixedRate,前者会等任务结束在开始计算时间间隔,后者是在任务开始就计算时间,有并发的情况

    二、使用ScheduledExecutorService

    1、ScheduledExecutorService

    scheduledExecutorService.schedule(new Runnable() {
                @Override
                public void run() {
                    System.out.println("ScheduledTask");
                }
            },1, TimeUnit.SECONDS);
    

    解释:延迟1s启动,执行一次

    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
            scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("ScheduledTask");
                }
            }, 1, 1, TimeUnit.SECONDS);
    

    解释:延迟1s启动,每隔1s执行一次,是前一个任务开始时就开始计算时间间隔,但是会等上一个任务结束在开始下一个

    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
            scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {
                    System.out.println("ScheduledTask");
                }
            }, 1, 1, TimeUnit.SECONDS);
    

    解释:延迟1s启动,在前一个任务执行完成之后,延迟1s在执行

    三、使用SpringTask

    1、写任务类

    package com.zb.timedtask;
    import com.zb.controller.StudentController;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    @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 定时任务!");
        }
    }
    

    解释:
    task1是每隔5s执行一次,{秒} {分} {时} {日期} {月} {星期}
    task2是延迟1s,每隔1S执行一次

    2、配置文件修改

    (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();
        }
    }
    

    四、使用Quartz框架

    1、加依赖

    <!-- 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>
    

    2、Job实现

    package com.zb.quartz;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    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!");
        }
    }
    

    3、调度器(可以用listener在项目启动时执行)

    import org.quartz.*;
    import org.quartz.impl.StdSchedulerFactory;
    
    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();
    

    4、整合spring

    也可以直接把上面的调度器写成配置文件,整合spring

    (1)job

    package com.zb.quartz;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class QuarFirstJob {
        public void first() {
            String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
            System.out.println( strTime + ":Hello World!");
        }
    }
    

    (2)配置文件

    <bean id="QuarFirstJob" class="com.zb.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>
    

    5、时间

    public class QuarFirstJob {
        public void first() {
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
            System.out.println( strTime + ":Hello World!");
        }
    }
    

    上面的配置里面写是5s间隔,把上面的sleep时间分别改成4和6,发现两次任务间隔是执行时间和间隔时间的最大值,分别是5,6

    总结

    Quartz是执行时间和间隔时间的最大值(比如;执行时间是3s,间隔是2s,则每3s执行一次;执行时间是3s,间隔是5s,则每5s执行一次。)
    Spring task是执行时间+间隔时间(比如;执行时间是3s,间隔是2s,则每5s执行一次;执行时间是3s,间隔是5s,则每8s执行一次。)
    timer有2中方法schedule和scheduleAtFixedRate,前者会等任务结束在开始计算时间间隔,后者是在任务开始就计算时间,有并发的情况
    ScheduledExecutorService的scheduleAtFixedRate类似Quartz,scheduleWithFixedDelay类似SpringTask

    相关文章

      网友评论

          本文标题:java定时任务

          本文链接:https://www.haomeiwen.com/subject/grasoftx.html