while(true)loop或java.util.Timer用于标准程序循环?

时间:2016-05-06 06:50:43

标签: java multithreading loops timer

最近我制作了一个非常基本的节目。一个具有暂停能力的计时器。它使用3个线程,2个用于Swing,1个用于主线程。

对于这个程序,主线程中应该有一个增量时间计数部分。我做了一个非常基本的系统;

while(true)
{
    long now = System.currentTimeMillis();

    if(!sessionPaused)
    {
        if(now-programLastMs>1000)
        {
            save();
            programLastMs = now;
        }
        sessionMs += now-sessionPrevMs;
        overallMs += now-sessionPrevMs;

        sessionPrevMs = now;
        sessionLabel.setText(formatMillis("This Session:<br/>",sessionMs));
        overallLabel.setText(formatMillis("Overall:<br/>", overallMs));
    }
}

上面的代码导致高CPU使用率。然后我用:

替换了那个代码块
timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

                long now = System.currentTimeMillis();

                if(!sessionPaused)
                {
                    if(now-programLastMs>1000)
                    {
                        save();
                        programLastMs = now;
                    }

                    sessionMs += now-sessionPrevMs;
                    overallMs += now-sessionPrevMs;

                    sessionPrevMs = now;

                    sessionLabel.setText(formatMillis("This Session:<br/>",sessionMs));
                    overallLabel.setText(formatMillis("Overall:<br/>", overallMs));
                }
            }
        }, 0, 1);

问题已经消失。我只是想知道原因。另外,创建程序循环的最佳方法是什么?

2 个答案:

答案 0 :(得分:5)

您的第一个代码块基本上以CPU的速度运行。要理解这一点,您需要知道IPSFLOPS是什么。 现代CPU可以执行一些GFLOPS,这意味着您的第一个块每秒会被执行数十甚至数十万次,具体取决于您的硬件。如果你在主线程上运行它,它将阻止你的UI(即你的GUI会卡住)。在一个单独的线程上,它将持续运行,而不会实际占用很多资源。

另一方面,第二个块具有每毫秒执行的特定指令。这意味着你的代码块被执行了1000次,其余的cpu时间被释放用于其他工作。

要解决您的评论中的问题:使用无限循环几乎是不可接受的。循环最好用于一组指令的有界重复。在您的示例中,您似乎希望每1000毫秒调用一次保存并计算会话时间。我会

  1. 将保存分配给每1000毫秒调用一次的重复计时器。
  2. 仅在暂停状态发生变化时创建onSessionPause和onSessionResume。这可能是由于您定义的暂停按钮或其他一些条件。 onSessionPause和onSessionResume函数应该能够记录它们的调用时间,并根据时间的差异更新sessionM。
  3. 除非你期望每毫秒改变一些事情,否则你会让CPU做不必要的工作。

答案 1 :(得分:1)

  

创建程序循环的最佳方法是什么?

在您的特定情况下,最佳方式是每秒运行一次循环,因为这将以最小的CPU使用率实现您的目标。由于这是不可能保证的,因此您需要找到足够低的阈值,因此您的循环至少每秒执行一次,而不是太低,以便有效。我建议你测试一些输出。

但要注意,不同的代码有不同的要求,因此没有通用的最佳方法来循环代码。作为一项基本规则,您应尽量避免尽可能多的冗余执行。