定时任务执行的几种常见方式

记录一下实现定时任务的几个方式:

1.使用线程池

主要是通过 newScheduledThreadPool 类类实现定时任务的线程池,下面贴一个示例代码:

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

public class ScheduledTaskExample {
    public static void main(String[] args) {
        // 创建线程池
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

        // 延迟1秒后开始执行任务
        executor.schedule(new Runnable() {
            @Override
            public void run() {
                // 在这里编写你要执行的定时任务代码
                System.out.println("执行定时任务");
            }
        }, 2, TimeUnit.SECONDS);

        // 等待一段时间后关闭线程池
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}

在上述示例中,ScheduledExecutorService类提供了用于创建定时任务的方法schedule()。该方法接受一个Runnable对象和一个时间参数,时间参数表示延迟多久开始执行任务。TimeUnit.SECONDS用于指定时间单位为秒。如果要执行间隔任务,把schedule()换成scheduleAtFixedRate()就行了,参数加多一个间隔时间参数,其余不变。

总结:

  • 优点:

    • 简单:使用Java自带的线程池类,无需引入额外的依赖。
    • 轻量级:不需要额外的框架或组件,适用于简单的定时任务需求。
    • 灵活性:可以自定义线程池的大小和参数,根据实际需求进行调整。
  • 缺点:

    • 任务管理较为简单:线程池一般只提供基本的任务管理功能,如定时执行、间隔执行等,对于更复杂的任务调度需求可能不够灵活。

2. Spring Task定时任务

首先在启动类上开启定时任务

@EnableScheduling

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

@Component
public class MyTaskScheduler implements SchedulingConfigurer {

    private final TaskScheduler taskScheduler;

    private String cron;  //动态修改此参数

    @Autowired
    public MyTaskScheduler(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }

    //1.必须调用changeTaskExecutionTime()方法,修改cron之后定时任务才会生效
    public void changeTaskExecutionTime() {
        // 修改定时任务的执行时间
        taskScheduler.schedule(() -> {
            // 执行定时任务的逻辑
            System.out.println("执行定时任务 1111");
        }, new CronTrigger("0/2 * * * * ?")); // 修改为每2秒执行一次
    }

    //2.启动则生效,可以动态修改cron表达式
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                ()->{
                    System.out.println("执行定时任务 2222 ");
                },new CronTrigger("0/2 * * * * ?")
        );
    }
}

 注:

        1. 此处要确保TaskScheduler的实例已经在应用程序的上下文中进行了配置,例如通过在另一个配置类中添加@Bean注解来创建和配置TaskScheduler的实例,例如:

在配置类里加上:

@Bean
public TaskScheduler taskScheduler(){
    // Spring提供的定时任务线程池类
    ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler();

    //设定最大可用的线程数目
    taskScheduler.setPoolSize(10);
    return taskScheduler;
}

        2. 确保在进行构造器注入时,有且只有一个符合条件的TaskScheduler实例存在,否则会导致注入失败或者出现歧义。

3. 第三方组件(Quartz)

首先,引入依赖

Gradle:

// https://mvnrepository.com/artifact/org.quartz-scheduler/quartz
implementation group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.2'

Maven:

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

创建一个实现了Job接口的执行任务类,该类主要定义任务的执行逻辑 ,例如:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // 在这里定义你的任务逻辑
        System.out.println("Hello, Quartz!");
    }
}

然后创建一个调度器以及实现任务的触发器,触发器定义了任务何时执行的规则:

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class Main {
    public static void main(String[] args) {
        try {
            // 创建调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            
            // 定义一个任务
            JobDetail job = JobBuilder.newJob(MyJob.class)
                    .withIdentity("myJob", "group1")
                    .build();
            
            // 定义触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(10) // 每10秒执行一次
                            .repeatForever()) // 无限重复执行
                    .build();
            
            // 将任务和触发器加入调度器
            scheduler.scheduleJob(job, trigger);
            
            // 启动调度器
            scheduler.start();
            
            // 等待一段时间,让任务执行
            Thread.sleep(60000);
            
            // 关闭调度器
            scheduler.shutdown();
        } catch (SchedulerException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

注:下面是几种常见的定时执行方式:

1. SimpleTrigger(简单触发器):按照给定的时间间隔和重复次数执行任务。

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger", "group1")
        .startAt(startDate) // 指定任务开始时间
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10) // 每10秒执行一次
                .withRepeatCount(5)) // 总共执行5次
        .build();

2. CronTrigger(Cron触发器):基于Cron表达式来定义任务的执行规则,可以实现更复杂的定时规则。

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger", "group1")
        .startAt(startDate) // 指定任务开始时间
        .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 每5秒执行一次
        .build();

 3. DailyTimeIntervalTrigger(每日时间间隔触发器):在每天指定的时间段内重复执行任务。

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger", "group1")
        .startAt(startDate) // 指定任务开始时间
        .withSchedule(DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule()
                .startingDailyAt(TimeOfDay.hourAndMinuteOfDay(9, 0)) // 每天9:00开始
                .endingDailyAt(TimeOfDay.hourAndMinuteOfDay(17, 0)) // 每天17:00结束
                .onDaysOfTheWeek(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY) // 仅在周一至周五执行
                .withIntervalInMinutes(30)) // 每30分钟执行一次
        .build();

 如果需要动态修改任务执行时间,则需要创建一个新的触发器来替换旧触发器,重新调度任务:

// 修改触发器的执行时间
TriggerKey triggerKey = new TriggerKey("myTrigger", "group1");
SimpleTrigger newTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
         .withIdentity(triggerKey)
         .startNow()
         .withSchedule(SimpleScheduleBuilder.simpleSchedule()
         .withIntervalInSeconds(5) // 每5秒执行一次
         .repeatForever())
         .build();

scheduler.rescheduleJob(triggerKey, newTrigger);

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值