如何在电脑进入睡眠模式时停止Java应用程序的运行
实现方案
该需求可以实现,核心逻辑为监听系统睡眠事件/识别睡眠后时间断层,触发逻辑停止你正在运行的定时任务线程即可,以下是两种常用实现方案:
方案1:跨平台通用轻量实现(无额外依赖,适配绝大多数场景)
无需对接系统原生API,通过时间差检测识别系统睡眠状态,逻辑简单稳定。
- 你的原有定时任务一般是基于
ScheduledExecutorService固定间隔调度,或者自定义线程sleep固定时长实现 - 改造逻辑:每次任务执行结束后记录当前时间戳,下次任务被唤醒执行时,先计算当前时间和上次记录时间的差值,如果差值远大于你预设的执行间隔,说明中间系统进入过睡眠,此时主动停止调度器、中断所有任务线程即可。
示例代码:
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class SleepDetectTask { // 预设的任务执行间隔,单位为秒 private static final long EXPECTED_INTERVAL = 60; // 允许的时间误差阈值,建议设为间隔的1.5倍 private static final long THRESHOLD = (long) (EXPECTED_INTERVAL * 1.5); private static long lastExecuteTime = System.currentTimeMillis() / 1000; private static ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public static void main(String[] args) { Runnable task = () -> { long currentTime = System.currentTimeMillis() / 1000; long gap = currentTime - lastExecuteTime; // 时间差超过阈值,判定系统经历过睡眠 if (gap > THRESHOLD) { System.out.println("检测到系统睡眠,停止任务执行"); scheduler.shutdownNow(); // 此处可添加你需要的程序退出前的资源清理逻辑 System.exit(0); } try { // 你的原有业务逻辑写在这里 System.out.println("执行定时任务,当前时间戳:" + currentTime); } finally { lastExecuteTime = currentTime; } }; // 启动定时调度,初始延迟0,间隔EXPECTED_INTERVAL秒执行 scheduler.scheduleAtFixedRate(task, 0, EXPECTED_INTERVAL, TimeUnit.SECONDS); } }
方案优缺点
- 优点:完全跨平台,不需要引入任何第三方依赖,逻辑简单不易出错
- 缺点:需要等到下次任务调度时才能检测到睡眠,无法在系统进入睡眠的瞬间触发停止逻辑
方案2:原生系统事件监听(实时响应,需适配不同操作系统)
如果需要系统进入睡眠的瞬间就立即停止程序,可以对接操作系统的电源管理事件实现,不同系统的实现逻辑不同:
- Windows平台:通过JNA调用Windows的
WM_POWERBROADCAST消息监听睡眠事件,收到PBT_APMSUSPEND事件(系统即将进入睡眠)时立即停止线程、退出程序 - Linux平台:监听
systemd-logind的DBus信号,或者读取/proc/acpi/event下的电源事件,检测到睡眠事件后触发停止逻辑 - macOS平台:调用IOKit框架的电源管理API,监听睡眠通知事件后执行停止逻辑
注意:方案2需要针对不同操作系统做定向适配,开发成本更高,若无实时响应的强需求,优先选择方案1即可。
内容的提问来源于stack exchange,提问作者Niket dubey
相关产品推荐
相关产品推荐

