如何在Java中实现每秒调用数据库获取状态,完成XML导入SQL基准测试?
实现文件删除事件触发后每秒查询数据库导入状态
要在文件删除事件触发后每秒调用数据库获取导入状态,核心是避免阻塞文件夹监控的主线程,同时实现定时查询逻辑。以下是两种可行的实现方案:
方案1:使用ScheduledExecutorService(推荐)
这种方式通过线程池管理定时任务,更规范且易于控制任务生命周期,适合生产环境。
修改后的完整代码:
import java.io.IOException; import java.nio.file.*; import java.time.Duration; import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.concurrent.*; public class Application extends SqlUtils { private static String folderPath = "D:\\EntityImportEversana"; // 单线程调度池,管理定时查询任务 private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public static void main(final String[] args) throws IOException, InterruptedException { System.out.println("Running file verifier"); System.out.println("monitoring folder " + folderPath); SqlUtils sql = new SqlUtils(); WatchService watchService = FileSystems.getDefault().newWatchService(); Path path = Paths.get(folderPath); path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); WatchKey key; while ((key = watchService.take()) != null) { for (WatchEvent<?> event : key.pollEvents()) { System.out.println("Event kind:" + event.kind() + ". File affected: " + event.context() + "."); if (event.kind().equals(StandardWatchEventKinds.ENTRY_DELETE)) { // 定义查询任务,支持自我取消 Runnable queryTask = new Runnable() { private Future<?> selfFuture; public void setSelfFuture(Future<?> future) { this.selfFuture = future; } @Override public void run() { Instant start = Instant.now(); HashMap<String, List> statusMap = sql.checkFileImport(); Instant end = Instant.now(); System.out.println("查询耗时: " + Duration.between(start, end)); // 根据业务逻辑判断导入是否完成,完成则取消任务 if (checkIfImportCompleted(statusMap)) { System.out.println("导入已完成,停止定时查询"); if (selfFuture != null) { selfFuture.cancel(false); } } } }; // 提交定时任务:延迟0秒启动,每秒执行一次 ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(queryTask, 0, 1, TimeUnit.SECONDS); queryTask.setSelfFuture(future); } } key.reset(); } watchService.close(); scheduler.shutdown(); // 程序退出时关闭线程池,避免资源泄漏 } // 自定义方法:根据数据库返回的状态判断导入是否完成 private static boolean checkIfImportCompleted(HashMap<String, List> statusMap) { // 示例逻辑:请根据你的业务需求修改 return statusMap != null && statusMap.containsKey("import_status") && statusMap.get("import_status").contains("SUCCESS"); } }
关键说明:
ScheduledExecutorService负责管理定时任务,不会阻塞WatchService的主线程,确保文件夹监控正常响应其他事件。- 每个删除事件对应一个独立的定时任务,任务内部判断导入状态,完成后自动取消。
- 必须实现
checkIfImportCompleted方法,贴合你的实际业务逻辑(比如检查导入状态字段、记录数等)。
方案2:使用普通线程(快速实现)
如果是简单场景,也可以直接启动新线程,通过Thread.sleep()实现每秒查询:
修改事件处理部分的代码:
if (event.kind().equals(StandardWatchEventKinds.ENTRY_DELETE)) { new Thread(() -> { while (true) { Instant start = Instant.now(); HashMap<String, List> statusMap = sql.checkFileImport(); Instant end = Instant.now(); System.out.println("查询耗时: " + Duration.between(start, end)); // 判断导入完成则退出循环 if (checkIfImportCompleted(statusMap)) { System.out.println("导入已完成,停止查询"); break; } try { Thread.sleep(1000); // 每秒执行一次 } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } }).start(); }
注意事项:
- 确保
SqlUtils.checkFileImport()是线程安全的,避免多线程调用时出现并发问题。 - 程序退出时要注意清理线程,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

