java 定时任务

一、Timer

这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。

复制代码
package com.wh.timingJob;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 文章摘自:https://www.jianshu.com/p/b6809b5a0c26
 * @Description //Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。
 *                      使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
 * @Author wanghao
 * @Date 2019-08-03 10:12
 **/
public class TestTimer {


    public static void main(String[] args) {

        // 声明任务
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task  run:"+ new Date());
            }
        };
        Timer timer = new Timer();
        //安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次
        /**
         *  @param task   task to be scheduled.     执行的任务
         *  @param delay  delay in milliseconds before task is to be executed.      任务执行前的延迟(毫秒)。
         *  @param period time in milliseconds between successive task executions.   连续任务执行之间的时间(毫秒)。
          */
        timer.schedule(timerTask,5000,3000);
    }
}
TestTimer
复制代码

代码如上,有加注释不再赘述。

二、ScheduledExecutorService

也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。

复制代码
package com.wh.timingJob;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description //ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,
 *                  每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
 * @Author wanghao
 * @Date 2019-08-03 10:17
 **/
public class TestScheduledExecutorService {



    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        /**
         *   @param command the task to execute
         *                      命令要执行的任务
         *   @param initialDelay the time to delay first execution
         *                      初始化延迟第一次执行的延迟时间
         *   @param period the period between successive executions
         *                      连续执行之间的时间段
         *   @param unit the time unit of the initialDelay and period parameters
         *                      参数单位初始延迟和周期参数的时间单位
         *   @return a ScheduledFuture representing pending completion of the task, and whose {@code get()} method will throw an exception upon cancellation
         *                      表示任务的挂起完成
         */
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("task "+Thread.currentThread().getName()+" ScheduledExecutorService "+new Date());
            };  //Time unit representing one second 表示一秒钟的时间单位
        },0,3,TimeUnit.SECONDS);


        // 参数:1、任务体 2、首次执行的延时时间
        //      3、任务执行间隔 4、间隔时间单位
        //service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);

    }
}
ScheduledExecutorService
复制代码

代码如上,有加注释不再赘述。

三、Quartz

这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。

Quartz需要添加依赖

如果SpringBoot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

如果是1.5.9则要使用以下添加依赖:

复制代码
<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>
</dependency>
复制代码

 1、单任务Quartz

首先创建一个任务

复制代码
package com.wh.timingJob.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Description //定时任务类
 * @Author wanghao
 * @Date 2019-08-04 21:40
 **/
public class TestTask1 extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("TestQuartz01----" + sdf.format(new Date()));
    }
}
TestTask1
复制代码

然后创建一个启动任务的

复制代码
package com.wh.timingJob.quartz;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-04 21:41
 **/

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail testQuartz1() {
        return JobBuilder.newJob(TestTask1.class).withIdentity("testTask1").storeDurably().build();
    }

    @Bean
    public Trigger testQuartzTrigger1() {
        //5秒执行一次
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(5)
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(testQuartz1())
                .withIdentity("testTask1")
                .withSchedule(scheduleBuilder)
                .build();
    }

    
}
QuartzConfig
复制代码

2、多个任务Quartz

 添加一个任务二

复制代码
package com.wh.timingJob.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-04 21:40
 **/
//Job - 由希望由调度程序执行的组件实现的接口。
public class TestTask2 extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("TestQuartz02----" + sdf.format(new Date()));
    }
}
TestTask2
复制代码

然后把启动类改为如下;

复制代码
package com.wh.timingJob.quartz;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-04 21:41
 **/

@Configuration
public class QuartzConfig {

    @Bean
    //JobDetail - 用于定义作业的实例。
    public JobDetail testQuartz1() {
        return JobBuilder.newJob(TestTask1.class).withIdentity("testTask1").storeDurably().build();
    }

    @Bean
    public Trigger testQuartzTrigger1() {
        //5秒执行一次
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(5)
                .repeatForever();
            return TriggerBuilder.newTrigger().forJob(testQuartz1())
                .withIdentity("testTask1")
                .withSchedule(scheduleBuilder)
                .build();
    }

    @Bean
    public JobDetail testQuartz2() {
        return JobBuilder.newJob(TestTask2.class).withIdentity("testTask2").storeDurably().build();
    }

    @Bean
    public Trigger testQuartzTrigger2() {
        //cron方式,每隔5秒执行一次
        return TriggerBuilder.newTrigger().forJob(testQuartz2())
                .withIdentity("testTask2")
                .withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?"))
                .build();
    }
}
QuartzConfig
复制代码

启动springboot即可。

3、另一种写法

 

复制代码
package com.wh.timingJob;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-03 10:46
 **/

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

/**
 * jar包依赖
 *
 * <dependency>
 *     <groupId>org.springframework.boot</groupId>
 *     <artifactId>spring-boot-starter-quartz</artifactId>
 * </dependency>
 */
public class TestQuartz implements Job {

    /**
     * 执行定时任务
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("TestQuartz quartz task "+new Date());
    }
}
TestQuartz1
复制代码
复制代码
package com.wh.timingJob;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-03 10:46
 **/

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

/**
 * jar包依赖
 *
 * <dependency>
 *     <groupId>org.springframework.boot</groupId>
 *     <artifactId>spring-boot-starter-quartz</artifactId>
 * </dependency>
 */
public class TestQuartz2 implements Job {

    /**
     * 执行定时任务
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("TestQuartz2222 quartz task "+new Date());
    }
}
TestQuartz2
复制代码
复制代码
package com.wh.timingJob;

import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-03 11:02
 **/

@Component
public class SchedulerAllJob {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    /**
     * @throws SchedulerException
     */
    public void scheduleJobs() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        /**
         *
         */
        scheduleJob1(scheduler);
        scheduleJob2(scheduler);
    }

    /**
     * 配置Job1
     * @param scheduler
     * @throws SchedulerException
     */
    private void scheduleJob1(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail = JobBuilder.newJob(TestQuartz.class) .withIdentity("job1", "group1").build();
        // 每5s执行一次
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);
    }
    /**
     * 配置Job
     * @param scheduler
     * @throws SchedulerException
     */
    private void scheduleJob2(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail = JobBuilder.newJob(TestQuartz2.class) .withIdentity("job2", "group1").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
        // 每10s执行一次
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1") .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);
    }

}
SchedulerAllJob
复制代码
复制代码
package com.wh.timingJob;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * @Description //TODO
 * @Author wanghao
 * @Date 2019-08-03 10:49
 **/


@Component
public class InitRunner implements CommandLineRunner {


    @Autowired
    SchedulerAllJob schedulerAllJob;

    @Override
    public void run(String... args) throws Exception {
        schedulerAllJob.scheduleJobs();
    }
}
InitRunner
复制代码

TestQuartz都是任务的实现

SchedulerAllJob 任务调度。

InitRunner  任务启动。

注:在使用SpringBoot构建项目时,我们通常有一些预先数据的加载。那么SpringBoot提供了一个简单的方式来实现–CommandLineRunner。换句话说就是,项目启动后就执行的

详情可点击链接:https://www.cnblogs.com/myblogs-miller/p/9046425.html   https://blog.csdn.net/qq_34531925/article/details/82527066

四、使用Spring Task

复制代码
package com.wh.timingJob;

/**
 * @Description // Spring Task:Spring3.0以后自带的task,
 *                  可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
 * @Author wanghao
 * @Date 2019-08-03 10:24
 **/

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 需要引入jar包依赖:
 * <dependencies>
 *   <dependency>
 *     <groupId>org.springframework.boot</groupId>
 *     <artifactId>spring-boot-starter-web</artifactId>
 *   </dependency>
 *   <dependency>
 *     <groupId>org.springframework.boot</groupId>
 *     <artifactId>spring-boot-starter</artifactId>
 *   </dependency>
 *   <dependency>
 *     <groupId>org.projectlombok</groupId>
 *     <artifactId>lombok</artifactId>
 *     <optional>true</optional>
 *   </dependency>
 *   <dependency>
 *     <groupId>org.springframework.boot</groupId>
 *     <artifactId>spring-boot-starter-test</artifactId>
 *     <scope>test</scope>
 *   </dependency>
 * </dependencies>
 */

/**
 * 例子:
 * # 每月的最后1天
 * @Scheduled(cron = "0 0 18 28–31 * ?")
 * public void doAtLastDayOfMonth() {
 *     final Calendar calendar = Calendar.getInstance();
 *     if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) {
 *         // do something here...
 *     }
 * }
 *
 * 说明:
 * Java(Spring)
 * *    *    *    *    *    *    *  springboot不支持年
 * -    -    -    -    -    -    -
 * |    |    |    |    |    |    |
 * |    |    |    |    |    |    + year [optional]
 * |    |    |    |    |    +----- day of week (0 - 7) (Sunday=0 or 7)
 * |    |    |    |    +---------- month (1 - 12)
 * |    |    |    +--------------- day of month (1 - 31)
 * |    |    +-------------------- hour (0 - 23)
 * |    +------------------------- min (0 - 59)
 * +------------------------------ second (0 - 59)
 */
@Component
@EnableScheduling
public class AlarmTask {

    /**默认是fixedDelay 上一次执行完毕时间后执行下一轮   springboot不支持年*/
    @Scheduled(cron = "0/5 * * * * *")
    public void run() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用cron  {}"+new Date());
        Thread.sleep(6000);
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用cron sleep 6 {}"+new Date());
    }

    /**fixedRate:间隔5s执行一次*/
    @Scheduled(fixedRate = 5000)
    public void run1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"=====>>>>>                             使用fixedRate  {}"+new Date());
    }

    /**fixedDelay:上一次执行完毕时间点之后5秒再执行*/
    @Scheduled(fixedDelay = 5000)
    public void run2() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"=====>>>>>                                                     使用fixedDelay  {}"+new Date());
    }

    /**第一次延迟2秒后执行,之后按fixedDelay的规则每5秒执行一次*/
//    @Scheduled(initialDelay = 2000, fixedDelay = 5000)
    public void run3(){
        System.out.println(Thread.currentThread().getName()+"=====>>>>>                                                                                 使用initialDelay  {}"+new Date());
    }



}
AlarmTask
复制代码

 

 

 这次写的都只是快速上手启动的模板,后期会贴上任务的详情介绍链接。

 

cron

cron表达式 每隔指定时间执行任务,
  例如:每个3秒执行,第一次01执行任务,任务执行4秒,第二次任务执行的时候判断任务仍然在执行则跳过,第三次执行任务的时候检查任务已经结束,开始执行任务,01+3+3>01+4所以是07开始下一次任务,如下图所示,定时任务轮询如果任务正在执行则跳过这次,如果检测任务没有运行则正常执行。

 

fixeddelay 

上一次任务执行结束等待间隔时间执行,这个很好理解,例如:间隔时间是3秒,01开始任务,任务执行4秒,下次任务执行时间就是01+4+3=08;

fixedrate

间隔时间执行,如果任务时间超出间隔时间,则下次任务再这次任务结束立即执行。例如:间隔时间是3秒,01开始任务,任务执行4秒,下次任务执行时间就是01+4=05;立即执行

 

 

 

复制代码
@Scheduled(cron ="${testCron2}")
    public void testCron2() {
        log.info("开始 testCron2  ---------");
    }


    @Scheduled(cron ="0/1 * * * * ? ")
    public void testCron() {
        log.info("开始 testCron  ---------");
    }


    @Scheduled(fixedRate = 3000)
    public void testFixedRate() throws InterruptedException {
        log.info("开始 testFixedRate  ---------");
        Thread.sleep(14000);
    }

    @Scheduled(fixedDelay = 3000)
    public void testFixedDelay() throws InterruptedException {
        log.info("开始 testFixedDelay  ---------");
        Thread.sleep(4000);
    }

    /**
     *  fixedDelayString 可以从配置文件获取
     */
    @Scheduled(fixedDelayString = "${fixedDelayString}")
    public void TestFixedDelayString() {
        log.info("开始 TestFixedDelayString  ---------");
    }

    /**
     *   fixedRateString 可以从配置文件获取
     */
    @Scheduled(fixedRateString = "${fixedRateString}")
    public void TestFixedRateString() {
        log.info("开始 TestFixedRateString  ---------");
    }
复制代码

配置文件

fixedDelayString: 4000
fixedRateString: 4000
testCron2: 0/1 * * * * ?

 

 

 

 

 

 

 

参考资料:

https://www.jianshu.com/p/b6809b5a0c26

posted @   苦心明  阅读(352)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示