Java 添加System.out.println()会降低执行速度(很多)?

Java 添加System.out.println()会降低执行速度(很多)?,java,while-loop,Java,While Loop,我有一个带有switch语句的while循环: while(true) { switch(state) { case LOADING : //THIS IS THE IMPORTANT PART //view loading screen (already set by default) contentPane.repaint(); if(tick == 400000)

我有一个带有switch语句的while循环:

while(true) {
        switch(state) {
        case LOADING :
            //THIS IS THE IMPORTANT PART
            //view loading screen (already set by default)
            contentPane.repaint();
            if(tick == 400000) {
                //state = GameState.MENU;
                System.out.println("Reached " + gameTick);
            }
            break;
        case MENU :
            //view menu
            break;
        //some other cases without content, left them out here
        }
        tick++;
        if(tick < 400000) {
                System.out.println(tick);
        }
        if(tick == Long.MAX_VALUE) {
            tick = 0;
        }
    }
(最后3行输出)

应用程序全屏显示,当我按下alt+tab键时,计数器通常在130K左右,我看到它移动到400K

但是,如果删除打印此数字的if语句:

if(tick < 400000) {
    System.out.println(tick);
}
if(勾选<400000){
系统输出打印项次(勾号);
}
加载屏幕从不移动,当我alt+tab退出时,已经达到400K

同样奇怪的是,加载屏幕有三个“外观变化”,一个是在100次调用它的paintComponent方法时,一个是在200次调用时,另一个是在300次调用时,这将计数器重置为0。所以基本上,每100个滴答声,它的外观就会发生变化。在第一种情况下,使用执行时间较长的if语句,我看到了变化,但远没有预期的频繁。在第二种情况下,我根本看不到它们(我可以想象它们发生得太快了)

所以我的问题是,是什么造成了执行时间上的巨大差异,是什么导致调用paintComponent方法的次数和循环迭代次数的差异


所有想法都被接受。

写入控制台,尤其是MS-DOS控制台,速度非常慢。您应该尽量减少写入控制台的行数。如果你必须写大量的数据,我建议你把它写到一个文件中,因为它可以大大加快速度

我假设这是在另一个线程中完成的,并且您没有占用GUI线程。

方法不会立即重新绘制组件,只会向AWT/Swing系统发出重新绘制组件的信号。因此,如果您调用
repaint()
fast 10次,它很可能只被重新绘制一次


现在,如果您查看循环,它不会执行任何需要很长时间的操作(请注意,
repaint()
不会重新绘制)。如果在循环中添加一个
System.out.println()
调用,将显著增加循环中要完成的工作。

写入控制台是一项相对耗时的任务,尤其是与什么都不做相比。这大大降低了执行速度。如果将输出重定向到文件,循环将比不打印时慢,但比打印到控制台时快

这就是有打印和无打印时执行速度差异很大的原因。

尝试以下操作:

tick++;
Thread.sleep(100);

并检查是否正在进行假定的更改。

任何类型的接口都比没有接口的速度慢很多倍。无论是控制台还是图形界面。这主要是因为访问图形设备需要所有额外的代码。更不用说硬件延迟。

应该会有帮助。难以置信(至少对我来说)写入控制台比写入文件慢得多。。无论如何,谢谢你的洞察力。然而,while循环的迭代次数和contentPane中paintComponent的调用量也存在差异。我刚刚添加了一行,它打印了一个计数器,显示了paintComponent执行的频率,并且每次都不同。在400K while()迭代中,该方法似乎被调用了255次(最低结果)到677次(最高结果)。它确实与屏幕上的变化量有关,即6。你能解释一下吗?GUI会尽力忽略虚假的绘制调用。只要超过实际需要的数字,不要太多就可以了。如果你考虑到在屏幕上打印一个字符所需的工作量,例如处理字体,那么它比写入一个不需要按每个字符执行任何操作的文件要慢也就不足为奇了。令人惊讶的是,MS-DOS窗口比同一台机器上的Swing GUI或xterm(运行Linux)慢得多。非常有用的背景知识。谢谢您的回答,现在一切都清楚了:)。现在我知道为什么调试是用写入文件的结果完成的了!感谢您的贡献:)。刚刚添加,结果都正常。把打印件拿出来会稍微短一点。现在让它休眠(1),这已经显著减慢了它的速度,看看这两个计数器是否因此变得更接近。在while循环的400K次迭代中,paintComponent现在使用sleep(1)调用了45662次。上述其他回答者解释了这种行为。谢谢你的贡献!是的,只需向while循环添加
Thread.sleep(2)
。无论如何,我不应该用一定数量的滴答来计时。这个解决方案仍然依赖于编译器来限制调用paintComponent()的次数,但是如果这给了我最高的刷新率,我会接受的。谢谢你的解释:)
tick++;
Thread.sleep(100);