Java案例怎么实现定时清理数据?

wen java案例 9

本文目录导读:

Java案例怎么实现定时清理数据?

  1. Timer + TimerTask(简单方案)
  2. ScheduledExecutorService(推荐方案)
  3. Spring @Scheduled(企业级方案)
  4. 完整的清理实现示例(结合数据库)
  5. 使用Quartz(分布式场景)
  6. 最佳实践建议

在Java中实现定时清理数据的常见方案有以下几种,我会从简单到复杂逐一介绍:

Timer + TimerTask(简单方案)

适用于简单场景,单线程执行:

import java.util.Timer;
import java.util.TimerTask;
public class DataCleanupExample {
    public static void main(String[] args) {
        Timer timer = new Timer("DataCleanupTimer");
        // 延迟1秒后开始,每24小时执行一次
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                cleanExpiredData();
            }
        }, 1000, 24 * 60 * 60 * 1000);
        // 或者使用相对时间
        // timer.schedule(new TimerTask() { ... }, new Date(), period);
    }
    private static void cleanExpiredData() {
        System.out.println("开始清理过期数据...");
        // 实际清理逻辑
        // 比如删除7天前的日志
        // DELETE FROM logs WHERE create_time < DATE_SUB(NOW(), INTERVAL 7 DAY)
    }
}

ScheduledExecutorService(推荐方案)

这是JDK推荐的方案,支持多线程:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledCleanupExample {
    private final ScheduledExecutorService scheduler;
    public ScheduledCleanupExample() {
        // 创建线程池,通常1-2个线程就够
        this.scheduler = Executors.newScheduledThreadPool(2);
    }
    public void startCleanupTask() {
        // 初始延迟1秒,每30分钟执行一次
        scheduler.scheduleAtFixedRate(() -> {
            try {
                performCleanup();
            } catch (Exception e) {
                // 异常处理,避免任务停止
                System.err.println("清理任务失败: " + e.getMessage());
            }
        }, 1, 30, TimeUnit.MINUTES);
    }
    private void performCleanup() {
        System.out.println("[" + new java.util.Date() + "] 执行数据清理...");
        // 示例:清理7天前的数据
        cleanupOldRecords("logs", 7);
        cleanupOldRecords("temp_files", 3);
    }
    private void cleanupOldRecords(String table, int days) {
        // 实际数据库操作
        // String sql = "DELETE FROM " + table + " WHERE create_time < ?";
        // jdbcTemplate.update(sql, new java.util.Date(System.currentTimeMillis() - 
        //     (long) days * 24 * 60 * 60 * 1000));
        System.out.println("清理表 " + table + " 中" + days + "天前的数据");
    }
    public void shutdown() {
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
    public static void main(String[] args) {
        ScheduledCleanupExample example = new ScheduledCleanupExample();
        example.startCleanupTask();
        // 程序运行时保持运行
        Runtime.getRuntime().addShutdownHook(new Thread(example::shutdown));
    }
}

Spring @Scheduled(企业级方案)

如果你的项目使用Spring框架,这是最简单的方式:

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableScheduling
public class ScheduledDataCleanup {
    // 每天凌晨2点执行
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanupDailyData() {
        System.out.println("执行每日数据清理...");
        // 清理逻辑
    }
    // 每30分钟执行一次
    @Scheduled(fixedRate = 30 * 60 * 1000)
    public void cleanupTempData() {
        System.out.println("清理临时数据...");
        // 清理逻辑
    }
    // 上次执行完后延迟10分钟再执行
    @Scheduled(fixedDelay = 600000)
    public void cleanupAfterPrevious() {
        System.out.println("上次清理完成后10分钟再执行...");
    }
    // 带初始延迟的任务
    @Scheduled(initialDelay = 5000, fixedRate = 3600000)
    public void cleanupWithDelay() {
        // 启动5秒后,每小时执行一次
    }
}

完整的清理实现示例(结合数据库)

import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DatabaseDataCleanup {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
    private static final String DB_USER = "root";
    private static final String DB_PASS = "password";
    public void cleanOldRecords() {
        String sql = "DELETE FROM user_logs WHERE create_time < ?";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            // 设置7天前的时间
            LocalDateTime cutoffDate = LocalDateTime.now().minusDays(7);
            pstmt.setObject(1, cutoffDate);
            int deletedCount = pstmt.executeUpdate();
            System.out.println("清理了 " + deletedCount + " 条过期记录");
        } catch (SQLException e) {
            System.err.println("数据库清理失败: " + e.getMessage());
        }
    }
    // 批量清理,避免大事务
    public void batchCleanup() {
        int batchSize = 1000;
        String sql = "DELETE FROM logs WHERE create_time < ? LIMIT ?";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
            int totalDeleted = 0;
            while (true) {
                pstmt.setObject(1, cutoffDate);
                pstmt.setInt(2, batchSize);
                int deleted = pstmt.executeUpdate();
                totalDeleted += deleted;
                if (deleted < batchSize) {
                    break; // 没有更多数据可删除
                }
                // 稍微暂停,避免数据库压力过大
                Thread.sleep(100);
            }
            System.out.println("总共清理了 " + totalDeleted + " 条记录");
        } catch (SQLException | InterruptedException e) {
            System.err.println("批量清理失败: " + e.getMessage());
        }
    }
}

使用Quartz(分布式场景)

对于分布式系统,推荐使用Quartz框架:

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzCleanupExample {
    public static void main(String[] args) throws SchedulerException {
        // 1. 定义Job
        JobDetail job = JobBuilder.newJob(CleanupJob.class)
                .withIdentity("dataCleanupJob", "cleanupGroup")
                .build();
        // 2. 定义触发器(每天凌晨3点)
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("cleanupTrigger", "cleanupGroup")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0 3 * * ?"))
                .build();
        // 3. 启动调度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}
// 自定义Job
class CleanupJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("执行定时清理任务...");
        // 清理逻辑
    }
}

最佳实践建议

  1. 选择合适的方案

    • 简单应用:ScheduledExecutorService
    • Spring应用:@Scheduled
    • 分布式系统:QuartzXXL-JOB
  2. 异常处理:确保任务不会因为一次失败就停止

  3. 日志记录:记录清理的开始、结束和执行情况

  4. 幂等性设计:确保多次执行结果一致

  5. 分批处理:大量数据时避免大事务

  6. 监控告警:清理失败时要能及时发现

选择哪种方案取决于你的项目规模、框架使用情况和业务复杂度。

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