应计算目标时间与当前时间的毫秒差,用单次javax.swing.Timer延迟执行提醒,避免轮询漏触发;delay>0时启动定时器,否则立即触发。

用 Swing 实现带时间选择和声音提醒的简易闹钟
Java 自带的 Swing 足够做出一个可运行的桌面闹钟,不需要引入第三方 GUI 库。核心是监听系统时间、比对设定时间、触发提醒动作——难点不在界面,而在「如何避免轮询卡主线程」和「提醒音播放的兼容性」。
为什么不能用 Timer 每秒检查一次?
直接用 javax.swing.Timer 每 1000ms 触发一次检查,看似简单,但容易漏掉设定时刻(比如 Timer 在 9:59:59.8 启动,下次触发是 10:00:00.8,刚好跳过 10:00:00.0 的整点)。更稳妥的方式是:计算距目标时间的毫秒差,用单次 Timer 延迟执行,避免持续轮询。
- 设定时间后,调用
System.currentTimeMillis()获取当前毫秒数 - 算出
delay = targetTimeMillis - System.currentTimeMillis() - 若
delay > 0,用new Timer(delay, e -> triggerAlarm()).start() - 若
delay ,说明已过期,立刻执行triggerAlarm()
播放提醒音时为什么 AudioSystem.getAudioInputStream() 报 UnsupportedAudioFileException?
Java 原生只支持 .wav(且需 PCM 编码),不支持 MP3、AAC 或其他格式。很多网上下载的“闹钟音效”其实是 MP3,直接传入会崩溃。
- 务必用工具(如 Audacity)将音频转为 16-bit PCM WAV,采样率建议 44100Hz
- 加载时用
getClass().getResource("/alarm.wav"),确保路径在 classpath 下 - 播放逻辑推荐用
Clip而非SourceDataLine,更轻量:
Clip clip = AudioSystem.getClip(); clip.open(AudioSystem.getAudioInputStream(alarmUrl)); clip.start();
关闭提醒窗口后声音还在继续播怎么办?
默认 Clip.start() 是异步非阻塞的,窗口关闭了线程还在播。必须显式停止并释放资源。
立即学习“Java免费学习笔记(深入)”;
- 把
Clip声明为类字段(而非局部变量),保证能被后续方法访问 - 在提醒弹窗的「确定」按钮点击事件里加
if (clip.isRunning()) clip.stop(); clip.close(); - 如果用户重复设置闹钟,记得先
if (clip != null && clip.isRunning()) clip.stop();再重载新音频
真正容易被忽略的是:WAV 文件体积大,反复加载会卡 UI;建议在初始化时就预加载一次 Clip,后续只调 clip.setFramePosition(0); clip.start();。









