int x = 1, y;
y = 0;
long time;
for(int k=0; k<8; k++) {
time = System.currentTimeMillis();
    for(long j=0; j<2000000000; j++)
     y = 2 * x;
    System.out.println("所用时间1:" + (System.currentTimeMillis() - time));    
    
    time = System.currentTimeMillis();
    for(long j=0; j<2000000000; j++)
     y = x << 1;
    System.out.println("所用时间2:" + (System.currentTimeMillis() - time));
    
    System.out.println();
}
程序运行结果
所用时间1:10312
所用时间2:8782所用时间1:9562
所用时间2:8734所用时间1:10047
所用时间2:8766所用时间1:10047
所用时间2:9078所用时间1:9859
所用时间2:9141
int x = 1, y;
y = 0;
long time;
for(int k=0; k<8; k++) {
time = System.currentTimeMillis();
    for(long j=0; j<2000000000; j++)
     y = x << 1;
    System.out.println("所用时间1:" + (System.currentTimeMillis() - time));    
    
    time = System.currentTimeMillis();
    for(long j=0; j<2000000000; j++)
     y = 2 * x;     
    System.out.println("所用时间2:" + (System.currentTimeMillis() - time));
    
    System.out.println();
}
结果:
所用时间1:10000
所用时间2:8703所用时间1:9188
所用时间2:8468所用时间1:9969
所用时间2:9125所用时间1:9891
所用时间2:8875所用时间1:9906
所用时间2:9125我想问下为什么放在后面的表达式所用的时间更短。

解决方案 »

  1.   

    我只发现一点,那就是for循环是时间的焦点,第一个for循环会很慢。原因未知!
      

  2.   


    紫竹, 我这边测的结果看来还不是for循环的问题啊..输出结果:
    移位-次序1:3703
    乘法-次序2:3735
    ===================================
    乘法-次序1:4078
    移位-次序2:3687
    package selfimpr.oa.web;public class Test2 { private static final long MAX = 999999999; /**
     * @param args
     */
    public static void main(String[] args) {
    // m1();
    // m2();
    // System.err.println("--------------------------------");
    // m2();
    // m1();
    // System.err.println("===================================");
    m3();
    System.err.println("===================================");
    m4();
    }

    private static void m3() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y <<= 1;
    System.out.println("移位-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z *= 2;
    System.out.println("乘法-次序2:" + (System.currentTimeMillis() - time));
    }

    private static void m4() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z <<= 1;
    System.out.println("移位-次序2:" + (System.currentTimeMillis() - time));
    } private static void m1() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法:" + (System.currentTimeMillis() - time)); } private static void m2() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = 0;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y = x << 1;
    System.out.println("移位:" + (System.currentTimeMillis() - time));
    }}
      

  3.   


    紫竹, 我这边测的结果看来还不是for循环的问题啊..输出结果:
    移位-次序1:3703
    乘法-次序2:3735
    ===================================
    乘法-次序1:4078
    移位-次序2:3687
    package selfimpr.oa.web;public class Test2 { private static final long MAX = 999999999; /**
     * @param args
     */
    public static void main(String[] args) {
    // m1();
    // m2();
    // System.err.println("--------------------------------");
    // m2();
    // m1();
    // System.err.println("===================================");
    m3();
    System.err.println("===================================");
    m4();
    }

    private static void m3() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y <<= 1;
    System.out.println("移位-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z *= 2;
    System.out.println("乘法-次序2:" + (System.currentTimeMillis() - time));
    }

    private static void m4() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z <<= 1;
    System.out.println("移位-次序2:" + (System.currentTimeMillis() - time));
    } private static void m1() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法:" + (System.currentTimeMillis() - time)); } private static void m2() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = 0;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y = x << 1;
    System.out.println("移位:" + (System.currentTimeMillis() - time));
    }}
      

  4.   

    确实是这样的啊~~~在程序在jvm的作用下运行时,*2的操作会被优化成移位操作,所以这两个的运行时间是一样的,如果将程序单独写在两个类中单独运行,时间基本相同。
    所用时间1:5953
    所用时间1:5953
    所用时间1:5937
    所用时间1:5953
    所用时间1:5954
    ------
    所用时间2:5969
    所用时间2:5953
    所用时间2:5968
    所用时间2:5954
    所用时间2:5968
    ------执行时间基本相同但为何出现楼主说的这种问题,期待高人的解答!
    不仅如此,经过实验,即使是都是移位操作或都是乘法操作,两次的时间差也会有不同。如下代码: long x = 1, y = 0;
            long time,time2;
            for(int k=0; k<5; k++) {
                time = System.currentTimeMillis();
                for(long j=0; j<2e8; j++)
                    y = x << 1;
                time2 = System.currentTimeMillis();
                System.out.println("所用时间1:" + (time2 - time));       
            }
    long x2=1, y2=0;
            long time3,time4;
            for(int l=0; l<5; l++) {    
                time3 = System.currentTimeMillis();
                for(long m=0; m<2e8; m++)
                    y2 = x2<<1;//2 * x;   
                time4 = System.currentTimeMillis();
                System.out.println("所用时间2:" + (time4 - time3));
            }在我机器上运行的结果是:经过修改循环次数,在可以区分出差别的范围内,如果循环次数扩大10倍,运行时间差也增大响应的倍数,所以估计时间的差异确实是循环产生的。
      

  5.   

    基本上搞明白了,但有一些不清楚的地方,我的结论是,
    1、如果连续两个相邻的相类似的结构的循环,java会做某种优化,具体怎么优化的不太清楚。
    2、对于循环体比较简单的循环,时间大部分花在了循环控制上。
    3、+,-,*这样的运算,时间差不多,区别不是太大。但/和%运算花的时间是前者7~8倍之多。
    4、for(long n=200000000;n>0;n--)这种结构的循环,在循环控制上花的时间,是与之相反的循环的近一倍。
    看我的测试:
    public class test6{
    public static void main(String [] args) {
    int x = 333333333, y;
            y = 0;
            long time;
            for(int k=0; k<8; k++) {
                time = System.currentTimeMillis();
                for(long j=0; j<2000000000; j++)
                    y = x *5;
                System.out.println("所用时间1:" + (System.currentTimeMillis() - time));  
                //****插入下面这个循环,目的是使前后两循环在执行顺序上相隔开。打乱java的优化。    
                for(long m=10000;m>1000;m--){
                 for(int n=0;n<100000;n++);
                }
                time = System.currentTimeMillis();
                for(long j=0; j<2000000000; j++)
                    y =  x<<2;                
                System.out.println("所用时间2:" + (System.currentTimeMillis() - time));
                
                System.out.println();
            }
    }
    }
    结果如下:
    F:\java>java test6
    所用时间1:7047
    所用时间2:7016所用时间1:7047
    所用时间2:7032所用时间1:7031
    所用时间2:7016所用时间1:7078
    所用时间2:7000所用时间1:7078
    所用时间2:7063所用时间1:7047
    所用时间2:7047所用时间1:7062
    所用时间2:7000所用时间1:7062
    所用时间2:7016如果把第二个循环的控制结构改为:for(long j=2000000000; j>0; j--)则运行结果如下:
    F:\java>java test6
    所用时间1:7078
    所用时间2:4031所用时间1:7079
    所用时间2:4031所用时间1:7094
    所用时间2:4032所用时间1:7078
    所用时间2:4031所用时间1:7078
    所用时间2:4031所用时间1:7078
    所用时间2:4046所用时间1:7079
    所用时间2:4031所用时间1:7078
    所用时间2:4031
      

  6.   

    4、for(long n=200000000;n>0;n--)这种结构的循环,在循环控制上花的时间,是与之相反的循环的近一半
      

  7.   

    这段程序两个循环一样的时候
    所用时间1:9188
    所用时间2:8187所用时间1:8891
    所用时间2:7796所用时间1:9000
    所用时间2:8110所用时间1:9281
    所用时间2:7969所用时间1:8938
    所用时间2:7890所用时间1:9219
    所用时间2:8078所用时间1:9281
    所用时间2:8094所用时间1:9109
    所用时间2:8063第二个改为for(long j=2000000000; j>0; j--)之后
    所用时间1:9266
    所用时间2:8813所用时间1:8984
    所用时间2:8906所用时间1:8969
    所用时间2:8797所用时间1:9032
    所用时间2:8922所用时间1:9640
    所用时间2:9000
      

  8.   


    也许吧..我按照13楼测的结果是4个方法运行下来, 两个循环的时间都基本相同....似乎没有什么优化...
    不过有一点发现...貌似jvm或者eclipse有缓存????基本上你第一次运行一个程序是什么结果,那么短时段内再次运行, 得到的时间结果好像差别不大.....
    package selfimpr.oa.web;import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;public class Test2 { private static final int MAX = 1111111111; /**
     * @param args
     */
    public static void main(String[] args) {
    // m1();
    // m2();
    // System.err.println("--------------------------------");
    // m2();
    // m1();
    // System.err.println("===================================");
    // m3();
    // System.err.println("===================================");
    // m4();
    m5();
    System.err.println("================================");
    m6();
    System.err.println("================================");
    m7();
    System.err.println("================================");
    m8();
    }

    private static void m5() {
    int x = 1;
    int y = 1;
    long time1 = System.currentTimeMillis();
    for(int i=0; i<MAX; i++) {
    x *= x;
    }
    System.out.println(System.currentTimeMillis() - time1);

    long time2 = System.currentTimeMillis();
    for(int i=0; i<MAX; i++) {
    y *= y;
    }
    System.out.println(System.currentTimeMillis() - time2);
    }

    private static void m6() {
    int x = 1;
    int y = 1;
    long time1 = System.currentTimeMillis();
    for(int i=MAX; i>0; i++) {
    x *= x;
    }
    System.out.println(System.currentTimeMillis() - time1);

    long time2 = System.currentTimeMillis();
    for(int i=MAX; i>0; i++) {
    y *= y;
    }
    System.out.println(System.currentTimeMillis() - time2);
    }

    private static void m7() {
    int x = 1;
    int y = 1;
    long time1 = System.currentTimeMillis();
    for(int i=0; i<MAX; i++) {
    x *= x;
    }
    System.out.println(System.currentTimeMillis() - time1);

    Set<String> interceptor = new HashSet<String>();
    for(Iterator<String> it = interceptor.iterator(); it.hasNext();) {
    it = interceptor.iterator();
    }

    long time2 = System.currentTimeMillis();
    for(int i=0; i<MAX; i++) {
    y *= y;
    }
    System.out.println(System.currentTimeMillis() - time2);
    }

    private static void m8() {
    int x = 1;
    int y = 1;
    long time1 = System.currentTimeMillis();
    for(int i=MAX; i>0; i++) {
    x *= x;
    }
    System.out.println(System.currentTimeMillis() - time1);

    Set<String> interceptor = new HashSet<String>();
    for(Iterator<String> it = interceptor.iterator(); it.hasNext();) {
    it = interceptor.iterator();
    }

    long time2 = System.currentTimeMillis();
    for(int i=MAX; i>0; i++) {
    y *= y;
    }
    System.out.println(System.currentTimeMillis() - time2);
    }

    private static void m3() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y <<= 1;
    System.out.println("移位-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z *= 2;
    System.out.println("乘法-次序2:" + (System.currentTimeMillis() - time));
    }

    private static void m4() {
    int x = 1, y, z;
    // y = Integer.MAX_VALUE;
    // z = Integer.MAX_VALUE;
    y = z = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法-次序1:" + (System.currentTimeMillis() - time));

    time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    z <<= 1;
    System.out.println("移位-次序2:" + (System.currentTimeMillis() - time));
    } private static void m1() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = x;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y *= 2;
    System.out.println("乘法:" + (System.currentTimeMillis() - time)); } private static void m2() {
    int x = 1, y;
    y = Integer.MAX_VALUE;
    y = 0;
    long time = System.currentTimeMillis();
    for (long j = 0; j < MAX; j++)
    y = x << 1;
    System.out.println("移位:" + (System.currentTimeMillis() - time));
    }}
      

  9.   


    public class Test1{
        public static void main(String [] args) {
            int x = 333333333, y;
            y = 0;
            long time;
            for(int k=0; k<4; k++) {
                time = System.currentTimeMillis();
                for(long j=0; j<2000000000; j++)
                    y = x << 2;
                System.out.println("所用时间1:" + (System.currentTimeMillis() - time));  
                //****插入下面这个循环,目的是使前后两循环在执行顺序上相隔开。打乱java的优化。    
                for(long m=10000;m>1000;m--){
                    for(int n=0;n<100000;n++);
                }
                time = System.currentTimeMillis();
                for(long j=0; j<2000000000; j++)
                    y =  x<<2;                
                System.out.println("所用时间2:" + (System.currentTimeMillis() - time));
                
                System.out.println();
            }
        }
    }
    两段一样的for循环,运行结果是
    所用时间1:19782
    所用时间2:18360所用时间1:19609
    所用时间2:18750所用时间1:19547
    所用时间2:18953所用时间1:19640
    所用时间2:18422
      

  10.   

    [Quote=引用楼主 java1109 的回复:]
    Java codeint x=1, y;
            y=0;long time;for(int k=0; k<8; k++) {
                time= System.currentTimeMillis();for(long j=0; j<2000000000; j++)
                    y=2* x;
                System.out.println("所用时间1:"+ (System.currentTimeMillis()- time));       
                
                time= System.currentTimeMillis();for(long j=0; j<2000000000; j++)
                    y= x<<1;
                System.out.println("所用时间2:"+ (System.currentTimeMillis()- time));
                
                System.out.println();
            }
    程序运行结果
    所用时间1:10312
    所用时间2:8782所用时间1:9562
    所用时间2:8734所用时间1:10047
    所用时间2:8766所用时间1:10047
    所用时间2:9078所用时间1:9859
    所用时间2:9141
    Java codeint x=1, y;
            y=0;long time;for(int k=0; k<8; k++) {
                time= System.currentTimeMillis();for(long j=0; j<2000000000; j++)
                    y= x<<1;
                System.out.println("所用时间1:"+ (System.currentTimeMillis()- time));       
                
                time= System.currentTimeMillis();for(long j=0; j<2000000000; j++)
                    y=2* x;                
                System.out.println("所用时间2:"+ (System.currentTimeMillis()- time));
                
                System.out.println();
            }
    结果:
    所用时间1:10000
    所用时间2:8703所用时间1:9188
    所用时间2:8468所用时间1:9969
    所用时间2:9125所用时间1:9891
    所用时间2:8875所用时间1:9906
    所用时间2:9125我想问下为什么放在后面的表达式所用的时间更短。通过横向和纵向比较,得出剩法运算比移位运算慢,这符合cpu计算原理,关键在于时间1比2快,期间函数只调用过库函数,我想更应该说过程2比1快,初始调用应该比以后的调用慢吧,只是说说,无确实证据!
      

  11.   

    这个问题估计涉及到jvm的内部运行机制问题,可以去问sun~~
      

  12.   

    居然有人在这里宣传赌博,CSDN果然是个大杂烩!
      

  13.   

    居然有人在这里宣传赌博,CSDN果然是个大杂烩!
      

  14.   


    我去详细研究了for(long n=200000000;n>0;n--)和for(long n=0; n<20000000000; n++)编译出来的东西的不同。地一种写法的循环确实要快。来看看分析过程先看普通的写法package test;public class Test {
    public static void main(String[] args) {
    for (int k =0; k<Integer.MAX_VALUE; k++)
    ; }
    }反编译
    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=2, Args_size=1
       0: iconst_0
       1: istore_1
       2: goto 8
       5: iinc 1, 1
       8: iload_1
       9: ldc #16; //int 2147483647
       11: if_icmplt 5
       14: return
      LineNumberTable: 
       line 5: 0
       line 8: 14  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      15      0    args       [Ljava/lang/String;
       2      12      1    k       I
    ===============================================================在看看这种写法
    package test;public class Test {
    public static void main(String[] args) {
    for (int k =Integer.MAX_VALUE; k>0; k--)
    ; }
    }
    反编译public static void main(java.lang.String[]);
      Code:
       Stack=1, Locals=2, Args_size=1
       0: ldc #16; //int 2147483647
       2: istore_1
       3: goto 9
       6: iinc 1, -1
       9: iload_1
       10: ifgt 6
       13: return
      LineNumberTable: 
       line 5: 0
       line 8: 13  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      14      0    args       [Ljava/lang/String;
       3      10      1    k       I注:我用的jdk是openJDK下面只把循环体那出来看//for (int k =0; k<Integer.MAX_VALUE; k++)
       5: iinc 1, 1
       8: iload_1
       9: ldc #16; //int 2147483647
       11: if_icmplt 5
    //for (int k =Integer.MAX_VALUE; k>0; k--)
       6: iinc 1, -1
       9: iload_1
       10: ifgt 6
    差别有2个,最后一句一个是if_icmplt.一个是ifgt.还有就是上面一个多了一个ldc我没查到资料一个指令到底需要多少cpu周期。而且在实际执行的时候,jvm会将指令转换为实际cpu指令,不同的硬件架构可能会不同。但是,我觉得有一点可以肯定。ifgt的周期不会大于if_icmplt. 而且ifgt只需要一个操作数。if_icmplt需要2个操作数。for (int k =0; k<Integer.MAX_VALUE; k++)这种写法,多了一个ldc指令,它执行的时间肯定比较常。
    总结:这2个写法的性能有差别,差别在于k>0和k<Integer.MAX_VALUE上面。