当前位置:首页 > 后端开发 > 正文

Java定时器如何实现

在Java中创建定时器常用两种方式:1. 使用 java.util.Timer和 TimerTask类,适合简单任务;2. 推荐采用 ScheduledExecutorService接口(通过 Executors.newScheduledThreadPool创建),支持多线程调度更灵活可靠,可周期性或延迟执行任务。

基础方案:java.util.Timer (单线程)

适用场景:简单单线程任务(如间隔日志备份)

import java.util.Timer; import java.util.TimerTask; public class BasicTimerExample { public static void main(String[] args) { Timer timer = new Timer(); TimerTask task = new TimerTask() { @Override public void run() { System.out.println("任务执行: " + new java.util.Date()); } }; // 延迟1秒启动,每2秒执行一次 timer.schedule(task, 1000, 2000); // 10秒后终止定时器 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } timer.cancel(); // 释放资源 } }

注意事项

  1. 单线程设计:一个任务阻塞会导致后续任务延迟
  2. 异常影响:任务抛出未处理异常会终止整个定时器
  3. 替代方案:Java 5+推荐用ScheduledExecutorService替代


推荐方案:ScheduledExecutorService (线程池)

适用场景:多任务并发、需资源控制(如订单状态轮询)

优势

  • 线程池管理:避免单点故障
  • 支持Callable:可获取任务返回值
  • 灵活调度:提供scheduleWithFixedDelay(任务结束到下次开始间隔)和scheduleAtFixedRate(固定频率)


Spring Boot集成方案:@Scheduled注解

适用场景:Spring项目快速集成(如定时数据同步)

  1. 启用定时配置(在启动类添加):

    Java定时器如何实现 第1张

  2. 创建定时任务类:

    @Component public class SpringScheduler { // 每5分钟执行(cron表达式) @Scheduled(cron = "0 */5 * * * ?") public void cronJob() { System.out.println("CRON任务: " + LocalDateTime.now()); } // 固定速率(上次开始后3秒) @Scheduled(fixedRate = 3000) public void fixedRateJob() { System.out.println("固定速率任务"); } // 带初始延迟(启动后2秒开始,每次间隔4秒) @Scheduled(initialDelay = 2000, fixedDelay = 4000) public void delayedJob() { System.out.println("延迟启动任务"); } }

    配置参数(application.properties):

    # 自定义线程池大小(默认单线程) spring.task.scheduling.pool.size=5
  3. 高级方案:Quartz框架

    适用场景:分布式调度、持久化存储(如跨服务器定时报表)

    Java定时器如何实现 第2张

    1. 添加依赖(Maven):

    2. 创建调度任务:

      public class QuartzJob implements Job { @Override public void execute(JobExecutionContext context) { System.out.println("Quartz任务触发: " + new Date()); } }

    3. public class QuartzScheduler {

      public static void main(String[] args) throws SchedulerException {

      // 1. 创建任务实例

      JobDetail job = JobBuilder.newJob(QuartzJob.class)

      .withIdentity(“reportJob”).build();

      // 2. 配置触发器(每10秒) Trigger trigger = TriggerBuilder.newTrigger() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(10) .repeatForever()) .build(); // 3. 启动调度器 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job, trigger); scheduler.start(); // 4. 关闭(实际应用中通过钩子关闭) Thread.sleep(30000); scheduler.shutdown(); } **核心优势**: - 集群支持:故障转移与负载均衡 - 持久化:任务状态存储到数据库 - 日历调度:排除节假日等特殊日期 --- ### **关键注意事项** 1. **线程安全**: - `Timer`和单线程`@Scheduled`需避免同步代码块 - 多线程方案中优先使用`Concurrent`集合类 2. **异常处理**: ```java executor.scheduleAtFixedRate(() -> { try { // 业务代码 } catch (Exception e) { logger.error("任务异常", e); } }, 0, 1, TimeUnit.SECONDS);

      1. 资源泄露预防
        • 所有调度器必须显式关闭(shutdown())
        • Spring项目中利用@PreDestroy注解
      2. 时间精度
        • 系统时钟跳变可能影响调度(考虑HashedWheelTimer)


      方案选型建议

      场景 推荐方案
      简单单机任务 ScheduledExecutorService
      Spring Boot项目 @Scheduled注解
      分布式/持久化需求 Quartz框架
      旧版Java兼容 Timer(谨慎使用)

      引用说明:本文代码示例基于Oracle官方Java 17 API文档、Spring Framework 5.3文档及Quartz Scheduler 2.3官方指南编写,关键实践参考《Java并发编程实战》(Brian Goetz著)中线程池管理原则。

      Java定时器如何实现 第3张

0