2014-12-04 68 views
1

对于一个简单的多线程的代码,如下所示,为什么计算需要更长时间的文字?

它需要41338 milliseconds于具有类似延迟

关闭主线程,始终如一地,如果我与int替换long,和比较等i < 0x7FFFFFFF它需要28 milliseconds始终与类似的延迟。

机功率:DELL E6430纬度上运行64位JVM 1.6

public class Dummy { 

    private static int NUM_OF_THREADS=200; 

    private static Thread[] thread = null; 

    public static void loopSomeTime(int i) { 
     thread[i] = new Thread(new Runnable(){ 
      public void run(){ 
       int count = 0; 
       for(long i = 0; i < 0x7FFFFFFFL; ++i){ 
        count++; 
       } 
       System.out.println(count); 
      } 
     }); 
     thread[i].start(); 

    } 


    public static void main(String[] args) throws InterruptedException{ 
     thread = new Thread[NUM_OF_THREADS]; 
     long beginTime = System.nanoTime(); 

     for(int i =0; i < NUM_OF_THREADS ; i++){ 
      loopSomeTime(i); 
     } 
     //I need to wait here 

     for(Thread eachThread : thread){ 
      eachThread.join(); 
     } 

     long endTime = System.nanoTime() - beginTime; 
     System.out.println("Time taken: " +endTime/(1000*1000) + " milliseconds"); 
    } 
} 

我解释的0x7FFFFFFFL等值64位机的价值0x7FFFFFFF作比较,这是2147483647

请帮助我了解延迟的差异。

+7

这是不是一个有用的做标杆的方法;你的数字将远离真实的表现。您需要担心诸如JIT热身等类似事情,实际上这意味着要使用精心设计的基准测试工具,如Caliper或JMH。你不能从你正在做的测量类型中得到任何有用的数字。 – 2014-12-04 19:48:11

+0

你确定你没有意外地在那里多加一个F吗? – Daniel 2014-12-04 19:48:36

+0

另外,如果你跑了两次程序,有可能第二次跑得更快 – Daniel 2014-12-04 19:49:08

回答

4

的代码是不一样的...... 这里是int版本的代码:

public void run(); 
    Code: 
     0: iconst_0 
     1: istore_1 
     2: iconst_0 
     3: istore_2 
     4: iload_2 
     5: ldc   #2     // int 2147483647 
     7: if_icmpge  19 
     10: iinc   1, 1 
     13: iinc   2, 1 
     16: goto   4 
     19: getstatic  #3     // Field java/lang/System.out:Ljava/io/PrintStream; 
     22: iload_1 
     23: invokevirtual #4     // Method java/io/PrintStream.println:(I)V 
     26: return 
} 

这里是long版本的代码:

public void run(); 
    Code: 
     0: iconst_0 
     1: istore_1 
     2: lconst_0 
     3: lstore_2 
     4: lload_2 
     5: ldc2_w  #2     // long 2147483647l 
     8: lcmp 
     9: ifge   22 
     12: iinc   1, 1 
     15: lload_2 
     16: lconst_1 
     17: ladd 
     18: lstore_2 
     19: goto   4 
     22: getstatic  #4     // Field java/lang/System.out:Ljava/io/PrintStream; 
     25: iload_1 
     26: invokevirtual #5     // Method java/io/PrintStream.println:(I)V 
     29: return 
} 

你可以观察到JVM使用的说明不一样。 int s递增,而long s使用算术。粗略地说:int代码使用寄存器而不是long之一。

这解释了至少在我的电脑上,也可能是你的差异。

它用java:

java version "1.8.0_20" 
Java(TM) SE Runtime Environment (build 1.8.0_20-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) 

和javac

javac 1.8.0_20 

上的MacOSX 10.9平台

我的JVM是64位...

+0

但是请注意,一个好的JITC会“消解”大部分的差异。 – 2014-12-04 20:33:25

+1

并注意这是由于int和long之间的差异。 '长*文字*'与它无关。 – EJP 2014-12-04 20:35:07

+0

@EJP - 有一种特殊情况,其中* javac *必须为“small”long类型文件(例如'5L')执行'ldc2_w',而相应的'int'代码将执行文字加载与'iconst_5'。 – 2014-12-04 22:47:11

相关问题