You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swing Timer调用start()创建过多实例导致运行加速问题求助

故障原因

  • 你当前的代码每次触发按钮点击事件时都会直接创建新的Timer实例,且没有持有旧实例的引用,无法主动终止还未执行完成的旧Timer。多个Timer同时在后台倒计时,到点后并行触发回调逻辑,就会表现为程序运行速度变快。
  • 你设置的LoginButton.setEnabled(false)防重复逻辑没有生效:如果用户在按钮完成置灰前快速多点了几次,会直接触发多次事件回调,创建多个Timer实例;就算按钮成功置灰,之前创建的未完成的Timer也依然会正常运行,不会自动销毁。
  • Swing Timer默认是重复触发的,如果没有设置单次执行,Timer会按照设定的间隔不断回调,也会加剧逻辑重复执行的问题。

修复方案

首先将Timer声明为类的成员变量,每次创建新Timer前先终止旧实例,避免多实例并行。修改后的参考代码如下:

// 首先在类中声明Timer成员变量
private Timer loginTimer;
// 原有类内的其他成员变量比如loginCounter、filepath等保持不变
// ...

// 按钮点击事件内的逻辑修改为以下内容
int delay;
ActionListener task;
loginCounter++;

// 启动新Timer前先停掉旧的,避免多实例并行
if (loginTimer != null && loginTimer.isRunning()) {
    loginTimer.stop();
    for (ActionListener al : loginTimer.getActionListeners()) {
        loginTimer.removeActionListener(al);
    }
}

if (loginCounter == 3) {
    LoginUnsuccesfulLabel.setText("密码连续输错3次,程序即将关闭...");
    LoginUnsuccesfulLabel.repaint();

    try {
        FileWriter w = new FileWriter(filepath + "report.log", true);
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        w.write(dtf.format(now) + " >>> [登录失败]\n");
        w.flush();
        w.close();
    } catch (IOException ex) {
        System.err.println("错误: " + ex.getMessage());
    }

    delay = 3000;
    task = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            LoginButton.setEnabled(true);
            LoginUnsuccesfulLabel.setText("");
            LoginUnsuccesfulLabel.repaint();
            System.exit(0);
        }
    };
} else {
    LoginUnsuccesfulLabel.setText("密码错误。");
    LoginUnsuccesfulLabel.repaint();
    delay = 1000;
    task = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            LoginButton.setEnabled(true);
            LoginUnsuccesfulLabel.setText("");
            LoginUnsuccesfulLabel.repaint();
        }
    };
}

LoginButton.setEnabled(false);
// 持有新Timer的引用,方便后续停止
loginTimer = new Timer(delay, task);
// 设置Timer只执行一次,避免重复回调
loginTimer.setRepeats(false);
loginTimer.start();

补充优化点

如果需要更严格的防重复点击,可以在事件回调开头第一行就给按钮置灰,避免用户快速点击触发多次逻辑。

内容的提问来源于stack exchange,提问作者Achille004

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:48:04