ScheduledExecutorService执行顺序不符预期的原因及解决方法
问题原因
ScheduledExecutorService基于线程池实现,调用scheduleAtFixedRate()只是把任务提交到线程池的任务队列,不会阻塞当前执行main方法的主线程。- 主线程提交任务后会立刻继续执行后续的
System.out.println("completed"),而线程池中的任务需要等待线程调度(哪怕延迟设为0,线程切换也存在微小开销),所以主线程的打印语句会先执行。
保证执行顺序的方法
结合你代码里“找到关键字就关闭线程池”的逻辑,提供几种实用方案:
方案1:让主线程等待线程池任务完成
提交任务后,用awaitTermination()让主线程阻塞,直到线程池关闭或者超时:
executor.scheduleAtFixedRate(periodicTask, 0, 5, TimeUnit.SECONDS); // 最多等待1分钟,可根据文件读取耗时调整时长 executor.awaitTermination(1, TimeUnit.MINUTES); System.out.println("completed");
注意:只有任务里触发executor.shutdown()后,awaitTermination才会结束阻塞;如果一直没找到关键字,超时后主线程会继续执行打印。
方案2:改用一次性任务并阻塞等待
如果你的需求只是执行一次文件查找(不是真的需要周期性执行),可以用submit()提交任务,再通过Future.get()阻塞主线程直到任务完成:
// 替换原有的scheduleAtFixedRate调用 Future<?> future = executor.submit(periodicTask); future.get(); // 主线程阻塞,直到任务执行完毕 executor.shutdown(); System.out.println("completed");
这种方式更贴合你“找到关键字就结束”的逻辑,避免不必要的周期性调度。
方案3:把后续逻辑放到任务内部
不想阻塞主线程的话,直接把System.out.println("completed")放到任务的最后执行,确保任务跑完才打印:
Runnable periodicTask = () -> { try { List<String> lines = Files.readAllLines(new File("E:\\MyFile.log").toPath()); String key = "FIND ME"; boolean found = false; for (String line : lines) { if (line.contains(key)) { count++; System.out.println("found text ..." + count); found = true; break; } } if (!found) { System.out.println("text not found"); } // 任务执行完成后再打印 System.out.println("completed"); if (found) { executor.shutdown(); } } catch (IOException e) { e.printStackTrace(); } };
这种方式由任务线程自己处理后续逻辑,主线程不需要等待。
内容的提问来源于stack exchange,提问作者Shivayan Mukherjee
相关产品推荐
相关产品推荐

