当前位置: 首页 > 面试题库 >

Java:空循环使用多少时间?

狄承望
2023-03-14
问题内容

我正在尝试测试Java中自动装箱和拆箱的速度,但是当我尝试将其与基元上的空循环进行比较时,我注意到了一件奇怪的事情。此代码段:

for (int j = 0; j < 10; j++) {
    long t = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++)
        ;
    t = System.currentTimeMillis() - t;
    System.out.print(t + " ");
}

每次运行此命令,它都会返回相同的结果:

6 7 0 0 0 0 0 0 0 0

为什么前两个循环总是要花一些时间,而其余的似乎只是被系统跳过了?

在这篇文章的答案中,据说即时编译将能够对此进行优化。但是,如果是这样,为什么前两个循环仍然需要一些时间?


问题答案:

在多次执行某段代码后,JIT会触发。

HotSpot
JVM将尝试识别代码中的“热点”。热点是您的代码片段,可以多次执行。为此,JVM将“计数”各种指令的执行,并且当它确定某个片段频繁执行时,它将触发JIT。(这是一个近似值,但是以这种方式很容易理解)。

JIT(即时)采用了这段代码,并试图使其更快。

JIT用来使代码运行更快的技术很多,但是最容易引起混淆的是:

  1. 它将尝试确定这段代码是否使用了其他地方没有使用的变量(无用的变量),并将其删除。
  2. 如果您多次获取并释放相同的锁(例如调用同一对象的同步方法),则它可以获取一次锁并在一个同步块中进行所有调用
  3. 如果访问未声明为volatile的对象成员,则可以决定对其进行优化(将值放置在寄存器等中),从而在多线程代码中产生奇怪的结果。
  4. 它将内联方法,以避免调用成本。
  5. 它将字节码转换为机器码。
  6. 如果循环完全没用,则可以将其完全删除。

因此,对您的问题的正确答案是,空循环在被JIT后,无需花费时间即可执行..很可能已经不存在了。

同样,还有许多其他优化,但是以我的经验来看,这些是最令人头疼的。

而且,JIT在任何新版本的Java中都得到了改进,有时根据平台的不同甚至有所不同(因为它在某种程度上是特定于平台的)。JIT所做的优化很难理解,因为您通常无法使用javap和检查字节码来找到它们,即使在Java的最新版本中,其中一些优化已直接移至编译器中(例如,自Java
6起,能够检测和警告未使用的局部变量和私有方法)。

如果要编写一些循环来测试某些东西,通常的好习惯是将循环包含在一个方法中,在对该方法进行计时之前对其进行几次调用,以使其“加速”运行,然后执行定时循环。

这通常会在像您这样的简单程序中触发JIT,即使无法保证它会实际触发(甚至存在于某个平台上)也是如此。

如果您想对JIT或非JIT时序抱有偏执(我做过),请执行以下操作:进行第一轮,对循环的每次执行进行时序安排,然后等待直到时序稳定为止(例如,与平均值相差小于10%),从您的“真实”时机开始。



 类似资料:
  • 问题内容: 我正在制作一个以这种方式执行的while循环程序: 主线程进入while循环。 在while循环中什么也没有发生。 线程将停留在while循环中,直到满足条件为止。 另一个线程运行一个满足上述条件的函数。 这是一个例子: 类中还有另一个函数会将路径设置为null,一旦发生这种情况,主线程应退出此循环。在另一个线程中调用另一个函数。 但是,即使将path设置为null,主线程也不会退出循

  • 问题内容: 有没有办法知道在Java中执行一个循环要花多少秒? 例如: 它不必精确到100%,而只是想知道要花费多长时间。里面的算法是一种写入.txt文件的密钥生成器。我希望它花费几分钟,因此对于我的第一次测试,我想计算秒数。 问题答案: 用Java编写微基准测试时需要非常小心。例如: 如果JIT编译器可以弄清楚循环体不影响代码结果,则可以对其进行优化。例如: 可能很快就会“运行”。 JIT编译后

  • 如何计算多个嵌套循环的时间复杂度?我已经完成了这段代码,但对它的时间复杂度感到困惑!

  • 这里是一个以圆圈为单位的交叉网格,当前为5x5。我试图得到一行5,下面是一行4,然后是3,然后是2等等。我试着改变for循环和值,但什么都不起作用。我需要使用行和列吗? 谢谢!

  • DB_示例我正在探索数据库的自动化测试,并努力在表中找到空值。 我想测试: > 如果EID2= 有null值,我得到以下错误:不能调用String.startswith(String),因为java.util.Map.get(对象)的返回值为null。 我的第一个值总是空的,所以我从计数器1开始循环,这解决了这个问题,但是我的表中的EID和CID中都有空值。如果不满足条件(即值为null),测试失

  • 为什么我们要在while循环后面加一个分号()? 我以以下代码为例: 那么在这里做什么呢?