Java定时任务

本文介绍了Java中的Timer类,Executors接口的使用,以及Spring框架如何在高并发场景下管理和配置定时任务,包括Cron表达式的应用和动态定时时间的两种配置方法。
摘要由CSDN通过智能技术生成

一、java.util.Timer

java.util.Timer 类允许您在未来的某个时间执行一个任务,或者在一定的时间间隔执行任务。您可以创建一个 Timer 实例,并调用其 schedule() 方法来安排任务的执行。这种方式比较简单,但在高并发环境下可能不够灵活。

1.代码实现

Timer timer = new Timer();
 //延迟1s,每个2s打印一次
 timer.schedule(new TimerTask() {
     @Override
     public void run() {
         System.out.println("111111111111");
     }
 }, 1000,2000);

2.常用方法

Timer 常用方法

二、java.util.concurrent.Executors

Java 提供了 ExecutorService 和 ScheduledExecutorService 接口,以及一些工厂方法来创建线程池和调度执行任务。ScheduledExecutorService 可以用于执行延迟任务或周期性任务。

1.代码实现

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(()->{
    System.out.println("1111111");
},1,2, TimeUnit.SECONDS);

2.常用方法

在这里插入图片描述

三、Spring Framework 定时任务

1.启用定时任务功能:

在配置类上添加 @EnableScheduling 注解,以启用 Spring 的定时任务功能。

@SpringBootApplication
@EnableScheduling
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

2.创建定时任务方法:

在 Spring 管理的 Bean 类中定义一个方法,并使用 @Scheduled 注解标记该方法作为定时任务。可以指定定时任务的触发时间、频率等。

@RestController
public class ScheduledTasksController {

    @Scheduled(cron = "0 30 9 * * ?")//每天九点半执行
    public void task1(){
        System.out.println("111111111");
    }

    @Scheduled(fixedRate = 5000)//每个5s执行
    public void task2(){
        System.out.println("222222222");
    }
}

3.cron表达式

每隔5秒执行一次:*/5 * * * * ?
每隔1分钟执行一次:0 */1 * * * ?
每天22点执行一次:0 0 22 * * ?
每天凌晨1点执行一次:0 0 1 * * ?
每月1号凌晨1点执行一次:0 0 1 1 * ?
每月最后一天21点执行一次:0 0 21 L * ?
每周星期天凌晨1点实行一次:0 0 1 ? * L
在12分、13分、14分执行一次:0 12,13,14 * * * ?
每天的0点、3点、5点、7点都执行一次:0 0 0, 3,5,7 * * ?
Java检测cron表达式
先引入quartz的jar包

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

检测代码

boolean validExpression = CronExpression.isValidExpression(cron);
if (validExpression) {
    //cron验证通过
} else {
    //cron颜值失败
}

四、动态配置定时时间

1.通过yml配置:

问题: 每次修改时间都需要重新启动服务;

@Component
@Slf4j
public class DynamicScheduledTaskRegistrar {
    @Resource
    private TaskScheduler taskScheduler;
    @Value("${schedule.cron}")
    private String cronExpression;

    @PostConstruct
    public void init() {
        scheduleTask();
    }

    private void scheduleTask() {
        Runnable task = () -> {
            //业务逻辑
        };
        Trigger trigger = new CronTrigger(cronExpression);
        taskScheduler.schedule(task, trigger);
    }
}

2.通过set动态配置

方式一
@Component
@Slf4j
public class DynamicScheduledTaskRegistrar {
    @Resource
    private TaskScheduler taskScheduler;

    private ScheduledFuture<?> scheduledFuture;
    private String cronExpression = "*/10 * * * * *"; // 默认的cron表达式

    @PostConstruct
    public void init() {
        scheduleTask();
    }

    private void scheduleTask() {
        Runnable task = () -> {
            // 这里写你的定时任务逻辑
            System.out.println("执行定时任务");
        };

        Trigger trigger = new CronTrigger(cronExpression);
        scheduledFuture = taskScheduler.schedule(task, trigger);
    }

    public void setCronExpression(String newCronExpression) {
        this.cronExpression = newCronExpression;

        // 取消之前的定时任务并重新调度
        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
            scheduledFuture.cancel(true);
        }
        scheduleTask();
    }
}
方式二

1.首先配置taskScheduler

@Configuration
@EnableScheduling
public class SchedulingConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10); // 设置线程池大小
        scheduler.setThreadNamePrefix("ScheduledTask-");
        scheduler.initialize();
        return scheduler;
    }
}

2.实现SchedulingConfigurer

@Component
@Slf4j
public class DynamicScheduledTask implements SchedulingConfigurer {
    private String cronExpression = ""; //cron 表达式
    private ScheduledFuture<?> scheduledFuture;

    private final TaskScheduler taskScheduler;

    public DynamicScheduledTask(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        scheduledFuture = taskScheduler.schedule(this::executeTask, new CronTrigger(cronExpression));
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
        // 根据新的 cron 表达式重新调度任务
        scheduledFuture.cancel(false);
        scheduledFuture = taskScheduler.schedule(this::executeTask, new CronTrigger(cronExpression));
    }

    public void executeTask() {
        // 定时任务执行的操作
        System.out.println("执行定时任务");
    }
}

不足之处望海涵

Java中有多种方式可以实现定时任务。其中比较常用的两种方式是使用Timer和TimerTask类,以及使用ScheduledThreadPoolExecutor类。 1. 使用Timer和TimerTask类: Timer和TimerTask是Java中用于定时任务的类。Timer负责设定TimerTask的起始与间隔执行时间,而TimerTask是一个抽象类,需要实现自己的run方法,并通过Timer进行执行。下面是一个示例代码: ```java import java.time.LocalDateTime; import java.util.Timer; import java.util.TimerTask; public class Schedule { public static void main(String[] args) { TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间:" + LocalDateTime.now()); } }; // 在指定延迟0毫秒后开始,随后每2000毫秒间隔执行timerTask new Timer().schedule(timerTask, 0L, 2000L); System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间:" + LocalDateTime.now()); } } ``` 在上面的示例中,创建了一个TimerTask对象,并实现了run方法来定义定时任务的逻辑。然后通过Timer的schedule方法来指定任务的延迟执行时间和间隔执行时间。 2. 使用ScheduledThreadPoolExecutor类: Java 5.0引入的java.util.concurrent包中的ScheduledThreadPoolExecutor类可以实现更灵活的定时任务。它是一个线程池,用于以给定的速率或延迟重复执行任务。相比于Timer和TimerTask的组合,ScheduledThreadPoolExecutor允许多个服务线程,并且不需要子类TimerTask(只需实现Runnable接口)。下面是一个示例代码: ```java import java.time.LocalDateTime; import java.util.concurrent.*; public class Schedule { public static void main(String[] args) { // 创建一个ScheduledThreadPoolExecutor线程池,心线程数为5 ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(5); // 创建Runnable打印当前线程和当前时间 Runnable r = () -> System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间:" + LocalDateTime.now()); /** * schedule:只执行一次调度 * scheduleAtFixedRate:一开始就计算间隔时间,如果任务超过间隔时间,那么就直接开始下一个任务 * scheduleWithFixedDelay:任务无论执行多久,都要等待上一轮任务完成之后再间隔指定时间,然后才开始下一个任务 */ // 在指定1秒延迟后执行r,之后每两秒执行一次 scheduledExecutorService.scheduleAtFixedRate(r, 1, 2, TimeUnit.SECONDS); } } ``` 在上面的示例中,首先创建了一个ScheduledThreadPoolExecutor线程池,核心线程数为5。然后创建一个Runnable对象,用于定义定时任务的逻辑。最后通过scheduleAtFixedRate方法来指定任务的延迟执行时间和间隔执行时间。 综上所述,Java中可以使用Timer和TimerTask类,以及ScheduledThreadPoolExecutor类来实现定时任务。选择哪种方式取决于具体的需求和场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值