Java案例如何实现定时任务?

wen java案例 11

本文目录导读:

Java案例如何实现定时任务?

  1. 使用 java.util.Timer(基础、简单)
  2. 使用 ScheduledExecutorService(推荐单机场景)
  3. 使用 Spring 的 @Scheduled 注解(企业级最常用)
  4. 使用 Quartz 框架(复杂场景、分布式)
  5. 各方案对比总结
  6. 常见Cron表达式示例

Java中实现定时任务有多种方式,从简单到复杂、从单机到分布式,各有适用场景,以下是几种最常用的实现方案及具体案例:

使用 java.util.Timer(基础、简单)

这是JDK自带的定时器,适合简单的单机任务。

import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo {
    public static void main(String[] args) {
        Timer timer = new Timer("MyTimer");
        // 延迟1秒后执行,之后每3秒执行一次
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行时间: " + System.currentTimeMillis());
            }
        }, 1000, 3000);
        // 程序运行10秒后停止
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        timer.cancel();
    }
}

缺点:所有任务使用单线程,一个任务异常会影响其他任务;不支持Cron表达式。


使用 ScheduledExecutorService(推荐单机场景)

线程池实现的定时任务,性能更好,支持多线程并发。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorDemo {
    public static void main(String[] args) {
        // 创建支持定时任务的线程池
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        // 任务1:固定速率执行(延迟1秒,每2秒执行一次)
        executor.scheduleAtFixedRate(() -> {
            System.out.println("任务1执行: " + Thread.currentThread().getName() 
                             + " - " + System.currentTimeMillis());
        }, 1, 2, TimeUnit.SECONDS);
        // 任务2:固定延迟执行(任务结束后固定延迟再执行)
        executor.scheduleWithFixedDelay(() -> {
            try {
                Thread.sleep(1000); // 模拟任务耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行: " + Thread.currentThread().getName());
        }, 1, 3, TimeUnit.SECONDS);
        // 让程序运行一段时间
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}

特点:支持多线程、异常处理更灵活、可返回Future。


使用 Spring 的 @Scheduled 注解(企业级最常用)

在Spring Boot项目中,这是最常用、最优雅的方式。

1 添加依赖

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

2 启动类启用定时任务

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling  // 启用定时任务
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3 编写定时任务

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class ScheduledTasks {
    // 1. 固定延迟:任务结束后延迟2秒再执行
    @Scheduled(fixedDelay = 2000)
    public void taskWithFixedDelay() {
        System.out.println("fixedDelay任务: " + LocalDateTime.now());
    }
    // 2. 固定速率:每3秒执行一次(不等待上一个任务完成)
    @Scheduled(fixedRate = 3000)
    public void taskWithFixedRate() {
        System.out.println("fixedRate任务: " + LocalDateTime.now());
    }
    // 3. 使用Cron表达式:每天10:15执行
    @Scheduled(cron = "0 15 10 * * ?")
    public void taskWithCron() {
        System.out.println("Cron任务: 每天10:15执行 - " + LocalDateTime.now());
    }
    // 4. 初始延迟:启动后5秒开始,之后每5秒执行
    @Scheduled(initialDelay = 5000, fixedRate = 5000)
    public void taskWithInitialDelay() {
        System.out.println("延迟任务: " + LocalDateTime.now());
    }
}

4 配置线程池(可选)

避免定时任务阻塞主线程,可自定义线程池:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulingConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(5);
        taskScheduler.setThreadNamePrefix("task-");
        return taskScheduler;
    }
}

使用 Quartz 框架(复杂场景、分布式)

适合需要持久化、集群、动态管理等复杂场景。

1 添加依赖

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

2 创建任务类

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class MyQuartzJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) 
            throws JobExecutionException {
        System.out.println("Quartz任务执行: " + System.currentTimeMillis());
        // 获取参数
        String param = context.getJobDetail().getJobDataMap().getString("param");
        System.out.println("参数: " + param);
    }
}

3 配置定时器

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail myJobDetail() {
        // 定义任务,绑定JobData参数
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("param", "hello");
        return JobBuilder.newJob(MyQuartzJob.class)
                .withIdentity("myJob", "group1")
                .usingJobData(jobDataMap)
                .storeDurably()
                .build();
    }
    @Bean
    public Trigger myTrigger() {
        // 定义触发器,Cron表达式:每5秒执行一次
        CronScheduleBuilder scheduleBuilder = 
            CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        return TriggerBuilder.newTrigger()
                .forJob(myJobDetail())
                .withIdentity("myTrigger", "group1")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

各方案对比总结

方案 优点 缺点 适用场景
Timer 简单、原生支持 单线程、异常影响大 极简单场景、JDK1.3+
ScheduledExecutorService 线程池、异常隔离 不支持Cron 单机中等复杂度
@Scheduled 注解开发、Cron支持 默认单线程 Spring Boot项目首选
Quartz 持久化、集群、动态管理 配置复杂、依赖重 企业级分布式场景

常见Cron表达式示例

0 0 12 * * ?       - 每天中午12点
0 0/5 * * * ?     - 每5分钟
0 0 8-18 * * ?    - 每天8点到18点每小时执行
0 0 0 1 * ?       - 每月1号零点
0 15 10 ? * 1-5   - 周一到周五10:15
0 0/30 9-17 * * ? - 9点到17点之间每30分钟

推荐选择:如果是Spring Boot项目,优先使用@Scheduled注解,简单高效;如果需要集群或持久化,再考虑Quartz。

抱歉,评论功能暂时关闭!