如何优化Java文件验证代码的循环?遇错误状态需终止执行
优化方案说明
原代码的嵌套while循环存在阻塞逻辑混乱、全表查询效率低、未处理错误状态的问题,以下是针对性优化后的实现:
核心优化点
- 将嵌套循环改为定时轮询+超时控制的逻辑,避免WatchService阻塞导致无法正常检测数据库状态
- 数据库查询改为按文件名精准查询,减少IO开销
- 新增错误状态检测逻辑,遇到错误直接终止流程并打印详情
- 提取独立方法封装状态检测逻辑,提升代码可读性
修改后的Application类代码
package com.file.verifier; import java.io.IOException; import java.nio.file.*; import java.time.Duration; import java.time.Instant; import java.util.List; import java.util.concurrent.TimeUnit; public class Application { private static final String FOLDER_PATH = "D:\\EntityImportEversana"; // 可配置的轮询参数 private static final long POLL_INTERVAL_SECONDS = 1; private static final long MAX_WAIT_MINUTES = 30; public static void main(final String[] args) throws IOException, InterruptedException { System.out.println("Running file verifier"); System.out.println("Monitoring folder: " + FOLDER_PATH); SqlUtils sqlUtils = new SqlUtils(); try (WatchService watchService = FileSystems.getDefault().newWatchService()) { Path path = Paths.get(FOLDER_PATH); // 只监听文件删除事件,缩小监听范围 path.register(watchService, StandardWatchEventKinds.ENTRY_DELETE); WatchKey key; while ((key = watchService.take()) != null) { for (WatchEvent<?> event : key.pollEvents()) { if (StandardWatchEventKinds.ENTRY_DELETE.equals(event.kind())) { String fileName = event.context().toString(); System.out.printf("Detected deletion of file: %s%n", fileName); monitorFileImportStatus(sqlUtils, fileName); } } key.reset(); } } } private static void monitorFileImportStatus(SqlUtils sqlUtils, String fileName) throws InterruptedException { Instant startTime = Instant.now(); boolean monitoring = true; while (monitoring) { // 查询当前文件的导入状态 List<String> statusInfo = sqlUtils.getFileImportStatus(fileName); if (statusInfo == null) { System.out.printf("Warning: No record found for file %s, retrying...%n", fileName); } else { String status = statusInfo.get(0); switch (status) { case "Completed": System.out.printf("File %s imported successfully%n", fileName); monitoring = false; break; case "Error": System.err.printf("Error processing file %s! Details: %s%n", fileName, statusInfo.get(1)); // 终止整个程序 System.exit(1); default: System.out.printf("File %s is still processing, current status: %s%n", fileName, status); } } // 检查是否超时 if (Duration.between(startTime, Instant.now()).toMinutes() >= MAX_WAIT_MINUTES) { System.err.printf("Timeout waiting for file %s to complete processing%n", fileName); System.exit(1); } TimeUnit.SECONDS.sleep(POLL_INTERVAL_SECONDS); } // 打印耗时 Duration duration = Duration.between(startTime, Instant.now()); System.out.printf("Processing time: %d minutes %d seconds%n", duration.toMinutes(), duration.getSeconds() % 60); } }
修改后的SqlUtils类代码
package com.file.verifier; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class SqlUtils { private static final String CONNECTION_URL = "jdbc:sqlserver://......"; // 按文件名精准查询状态,避免全表扫描 public List<String> getFileImportStatus(String fileName) { String query = "SELECT Status, ErrorMessage, OtherDetails FROM integration.EntityImportRequests WHERE FileName = ?"; try (Connection connection = DriverManager.getConnection(CONNECTION_URL); PreparedStatement stmt = connection.prepareStatement(query)) { stmt.setString(1, fileName); try (ResultSet resultSet = stmt.executeQuery()) { if (resultSet.next()) { List<String> statusInfo = new ArrayList<>(3); statusInfo.add(resultSet.getString("Status")); statusInfo.add(resultSet.getString("ErrorMessage")); statusInfo.add(resultSet.getString("OtherDetails")); return statusInfo; } } } catch (SQLException e) { System.err.println("Database query failed:"); e.printStackTrace(); // 数据库异常直接终止 System.exit(1); } return null; } }
关键优化细节
轮询逻辑重构:
- 移除嵌套的WatchService循环,改用定时休眠+主动查询数据库的方式,避免WatchService阻塞导致状态检测停滞
- 添加最大等待超时时间,防止无限轮询
数据库查询优化:
- 使用
PreparedStatement按文件名精准查询,避免全表扫描,提升查询效率 - 只查询需要的字段(状态、错误信息等),减少数据传输
- 使用
错误处理增强:
- 检测到"Error"状态时,打印错误详情并直接终止程序
- 数据库查询异常时,打印堆栈信息并终止
- 添加超时终止逻辑,避免无限等待
代码可读性提升:
- 将状态检测逻辑提取到独立方法
monitorFileImportStatus中 - 使用常量定义配置参数,便于后续修改
- 格式化输出日志,更清晰直观
- 将状态检测逻辑提取到独立方法
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

