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我想问下为什么放在后面的表达式所用的时间更短。
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我想问下为什么放在后面的表达式所用的时间更短。
紫竹, 我这边测的结果看来还不是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));
}}
紫竹, 我这边测的结果看来还不是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));
}}
所用时间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倍,运行时间差也增大响应的倍数,所以估计时间的差异确实是循环产生的。
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
所用时间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
也许吧..我按照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));
}}
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
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快,初始调用应该比以后的调用慢吧,只是说说,无确实证据!
我去详细研究了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上面。