Java中如何等待Swing Timer停止?解决循环等待致程序冻结问题
解决Swing Timer等待执行停止时程序冻结的问题
嘿,这个坑我刚接触Swing的时候也踩过!你用while(timer.isRunning()){}等待的方式之所以无效还导致程序冻结,核心原因是Swing的单线程模型限制——咱们得先搞清楚为什么会这样,再给你靠谱的解决方案。
为什么while循环会导致冻结?
Swing的所有UI操作、Timer的任务逻辑都是在**事件调度线程(EDT)**中执行的。当你调用启动Timer的方法后,马上进入while循环,这个循环会死死霸占EDT,导致Timer的任务根本没机会被调度执行——EDT被你的while循环占满了,timer.isRunning()永远返回true,程序自然就卡住不动了。
推荐的解决方案
方案1:用ActionListener回调(最符合Swing设计)
这是Swing官方推荐的方式,不需要主动等待,而是让Timer执行完毕后主动通知你后续逻辑。
场景1:Timer只执行一次
// 创建只执行一次的Timer(间隔1000ms) Timer timer = new Timer(1000, e -> { // Timer执行完成后,这里写你需要后续执行的逻辑 System.out.println("Timer执行完毕,开始处理后续任务"); // 如果需要操作UI,直接在这里写就行(因为ActionListener在EDT中执行) yourLabel.setText("Timer已停止"); }); timer.setRepeats(false); // 设置为只执行一次 timer.start();
场景2:Timer重复执行N次后停止
// 用数组存执行次数(lambda需要访问有效final变量) int[] executeCount = {0}; final int MAX_COUNT = 5; Timer timer = new Timer(1000, e -> { executeCount[0]++; System.out.println("Timer执行第" + executeCount[0] + "次"); if (executeCount[0] == MAX_COUNT) { // 停止Timer ((Timer) e.getSource()).stop(); // 执行后续逻辑 System.out.println("Timer已完成所有执行,开始后续操作"); yourButton.setEnabled(true); } }); timer.start();
方案2:用CountDownLatch实现同步等待(适合必须阻塞等待的场景)
如果你的业务逻辑必须同步等待Timer完成,那绝对不能在EDT里等待,得把等待逻辑放到单独的线程中,同时用CountDownLatch来实现线程间的通知:
import java.util.concurrent.CountDownLatch; import javax.swing.SwingUtilities; // 创建一个CountDownLatch,计数为1(表示等待一个事件) CountDownLatch latch = new CountDownLatch(1); Timer timer = new Timer(1000, e -> { ((Timer) e.getSource()).stop(); latch.countDown(); // 通知等待的线程:Timer已停止 }); timer.start(); // 新开一个线程执行等待逻辑,避免阻塞EDT new Thread(() -> { try { latch.await(); // 等待Timer完成 System.out.println("Timer已停止,继续后续任务"); // 如果需要操作UI,必须切换回EDT SwingUtilities.invokeLater(() -> { yourFrame.setTitle("Timer执行完毕"); }); } catch (InterruptedException ex) { // 处理中断异常 Thread.currentThread().interrupt(); } }).start();
总结
优先选择方案1的回调模式,它完全符合Swing的单线程设计思想,不会阻塞UI,代码也更简洁。只有当业务逻辑必须同步等待时,再考虑方案2,但一定要注意线程切换,绝对不能在EDT中执行等待操作。
内容的提问来源于stack exchange,提问作者Yoshie2000
相关产品推荐
相关产品推荐

