老计时器不会停止

时间:2014-04-04 17:17:58

标签: java timer

当第一个问题出现时我启动计时器,它会回来。如果用户及时回答问题,我希望计时器完全取消并启动新的计时器。但是,当用户回答问题时,在第二个问题中,第一个计时器仍在处理。

这是我的计时器方法:

public Timer myTimer() {
    timer = new Timer();
    timerTask = new TimerTask() {
        @Override
        public void run() {
            sec--;
            if (sec<0) {

                this.cancel();

                game.dispatchEvent(new WindowEvent(game, WindowEvent.WINDOW_CLOSING));
                JOptionPane.showMessageDialog(null, "GAME OVER!\nYour score: " + score);

                scoreJSON = new ScoreJSON(playerName, score);
                scoreJSON.write();

            } else if (sec<10) {
                time.setText("0" + String.valueOf(sec));
            } else {
                time.setText(String.valueOf(sec));
            }
        }
    };
    timer.schedule(timerTask, 1000, 1000);
    return timer;
}

这是用户回答问题的另一种选择:

a.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent arg0) {
        checkAnswer("answer0");
        myTimer();
    }
});

2 个答案:

答案 0 :(得分:1)

我重新设计了myTimer()方法,发现在cancel()实例(而不是Timer)上调用TimerTask会正确停止计时器。发生这种情况是因为在cancel()上调用TimerTask可能会取消任务,但不会取消计时器。下面的代码显示了我用来测试的类。

public class TimerTest {
    public static final int TIMEOUT = 5;
    private static Timer timer;

    public static void main(String[] args) {
        // Creates and starts the Timer. The TimerTask cancels the Timer when
        // it's done, so we don't need to keep a reference to it.
        timer = myTimer(TIMEOUT);

        try {
            // Suppose the correct answer is given after 2.5 seconds
            Thread.sleep(2500);
        } catch (InterruptedException e) {
        }
        timer.cancel();
        System.out.println("Timer interrupted by main");
    }

    public static Timer myTimer(final int timeout) {
        // We keep the Timer instance with the TimerTask, to prevent us from
        // having to worry about managing multiple timers. Each Timer is
        // guaranteed to stop when sec drops to 0.
        final Timer t = new Timer();
        TimerTask timerTask = new TimerTask() {
            // We keep the current time in each TimerTask. This ensures that
            // multiple TimerTasks will not interfere with each other.
            private int sec = timeout;
            @Override
            public void run() {
                sec--;
                if (sec < 0) {
                    t.cancel(); // cancel the Timer here.
                    System.out.println("Timer stopped by TimerTask");
                } else {
                    // Replace this with whatever you do each second
                    System.out.println("Current time: " + (sec < 10 ? "0" : "") + sec + " seconds");
                }
            }
        };
        t.schedule(timerTask, 1000, 1000);
        return t;
    }
}

运行该示例启动一个Timer,然后在2.5秒后停止它(这也会退出JVM,因为没有更多正在运行的线程)。将TimerTask中的t.cancel()更改为this.cancel()似乎取消了该任务(不再打印任何内容),但无法取消定时器(JVM继续运行)。

答案 1 :(得分:0)

你需要有办法安全地停止线程。看看这个选项:The Safe Way to Stop a Thread by Bruce Eckel。这样,您可以在正在运行的计时器线程上调用requestStop,然后启动一个新线程。您必须保存对您启动的每个计时器线程的引用,以便稍后可以在其上调用.requestStop方法。