JDK源码中为什么在方法中创建一个临时变量替代成员变量、类变量 又名 临时变量提高Java代码性能
一个Java类中可以存在多种形式的变量,可以是最一般的成员变量;或静态变量;或临时变量。那么这三种变量的存取效率如何?
1、实战出真知
package com.subject.variable;
/**
* 使用临时变量提高Java代码性能 (转)
*/
public class VariableDemo {
private long instVar;// 成员变量
private static long staticVar; // 静态变量
// 存取类方法中的临时变量
void tempAccess(long val) {
int j = 0;// 临时变量
long startTime = System.currentTimeMillis();
for (long i = 0; i < val; i++) {
j += 1;
}
long endTime = System.currentTimeMillis();
System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
}
// 存取类的成员变量
void instanceAccess(long val) {
long startTime = System.currentTimeMillis();
for (long i = 0; i < val; i++) {
instVar += 1;
}
long endTime = System.currentTimeMillis();
System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
}
// 存取类的 static 变量
void staticAccess(long val) {
long startTime = System.currentTimeMillis();
for (long i = 0; i < val; i++) {
staticVar += 1;
}
long endTime = System.currentTimeMillis();
System.out.println("static var: " + (endTime - startTime) + " milli seconds");
}
public static void main(String[] args) {
VariableDemo test = new VariableDemo();
long count=10*1000*1000*1000L;
test.tempAccess(count);
test.instanceAccess(count);
test.staticAccess(count);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
计算结果:
temp var: 2987 milli seconds
instance var: 4039 milli seconds
static var: 3996 milli seconds
- 1
- 2
- 3
这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 tempAccess 使一个局部堆栈变量递增,instanceAccess 使类的一个成员实例变量递增,而 staticAccess 使类的一个 static 变量递增。
从结果中可以发现,instanceAccess 和 staticAccess 的执行时间基本相同。但是,tempAccess 要快两到三倍。
2、JVM存取变量机制
存取堆栈变量如此快是因为JVM 存取堆栈变量比它存取 成员变量 或 静态变量执行的操作少。
JVM 是一种基于堆栈的虚拟机,因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,在 Java 操作数堆栈中进行处理,并可被高效地存取。
存取 成员变量 和 静态变量 成本更高,因为 JVM 必须使用代价更高的操作码,并从常数存储池中存取它们。(常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。)通常,在第一次从常数存储池中访问 static 变量或实例变量以后,JVM 将动态更改字节码以使用效率更高的操作码。尽管有这种优化,堆栈变量的存取仍然更快。
3、那么如何优化代码
考虑到这些事实,就可以重新构建前面的代码,以便通过存取堆栈变量而不是实例变量或 static 变量使操作更高效。
package com.subject.variable;
/**
* 使用临时变量提高Java代码性能 (转)
*/
public class VariableDemo2 {
private long instVar;// 成员变量
private static long staticVar; // 静态变量
// 存取类方法中的临时变量
void tempAccess(long val) {
int j = 0;// 临时变量
long startTime = System.currentTimeMillis();
for (long i = 0; i < val; i++) {
j += 1;
}
long endTime = System.currentTimeMillis();
System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
}
// 存取类的成员变量
void instanceAccess(long val) {
long startTime = System.currentTimeMillis();
long tmp=instVar;
for (long i = 0; i < val; i++) {
tmp += 1;
}
instVar=tmp;
long endTime = System.currentTimeMillis();
System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
}
// 存取类的 static 变量
void staticAccess(long val) {
long startTime = System.currentTimeMillis();
long tmp=staticVar;
for (long i = 0; i < val; i++) {
tmp += 1;
}
staticVar=tmp;
long endTime = System.currentTimeMillis();
System.out.println("static var: " + (endTime - startTime) + " milli seconds");
}
public static void main(String[] args) {
VariableDemo2 test = new VariableDemo2();
long count=10*1000*1000*1000L;
test.tempAccess(count);
test.instanceAccess(count);
test.staticAccess(count);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
计算结果:
temp var: 2973 milli seconds
instance var: 3074 milli seconds
static var: 3018 milli seconds
- 1
- 2
- 3
我觉得还有个原因:
这样可以保证原来的数据不被改变 ,这个是个人理解,如有不对请海量
转载来源
https://blog.csdn.net/hl_java/article/details/79288909