最近我制作了一个非常基本的节目。一个具有暂停能力的计时器。它使用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);
问题已经消失。我只是想知道原因。另外,创建程序循环的最佳方法是什么?
答案 0 :(得分:5)
您的第一个代码块基本上以CPU的速度运行。要理解这一点,您需要知道IPS和FLOPS是什么。 现代CPU可以执行一些GFLOPS,这意味着您的第一个块每秒会被执行数十甚至数十万次,具体取决于您的硬件。如果你在主线程上运行它,它将阻止你的UI(即你的GUI会卡住)。在一个单独的线程上,它将持续运行,而不会实际占用很多资源。
另一方面,第二个块具有每毫秒执行的特定指令。这意味着你的代码块被执行了1000次,其余的cpu时间被释放用于其他工作。
要解决您的评论中的问题:使用无限循环几乎是不可接受的。循环最好用于一组指令的有界重复。在您的示例中,您似乎希望每1000毫秒调用一次保存并计算会话时间。我会
除非你期望每毫秒改变一些事情,否则你会让CPU做不必要的工作。
答案 1 :(得分:1)
创建程序循环的最佳方法是什么?
在您的特定情况下,最佳方式是每秒运行一次循环,因为这将以最小的CPU使用率实现您的目标。由于这是不可能保证的,因此您需要找到足够低的阈值,因此您的循环至少每秒执行一次,而不是太低,以便有效。我建议你测试一些输出。
但要注意,不同的代码有不同的要求,因此没有通用的最佳方法来循环代码。作为一项基本规则,您应尽量避免尽可能多的冗余执行。