for循环一次的时间耗费在5个单位左右,本地int变量赋值一次的时间耗费在1-2个单位。下表列出了各种操作的时间耗费:
操作 时间耗费
int var = var 1.5
int array[0] = array[0] 4
for 6
throw --- catch 5000
下表是各种类型之间转化的时间耗费:
转化形式 时耗
SubClass = (SubClass) SuperClass 4
Interface = (Interface) Class 4
int à byte, intà char, intà short, intà long 1
intàfloat, intàdouble 3
intß long 10-15
intß float, intß double 15-20
longß float, longß double 30-40
以上时间消耗是个参考。
尽量使用局部变量
下面给出一段代码示例,对比后说明怎么尽可能地使用stack变量:
public class StackVars {
private int x; // instance变量
private static int staticX; //static 变量
public void stackAccess(int val) { //访问和操作stack变量j
int j = 0;
for (int i = 0; i < val; i++) {
j += 1;
}
}
public void instanceAccess(int val) {//访问和操作instance变量x
for (int i = 0; i < val; i++) {
x += 1;
}
}
public void staticAccess(int val) {//访问和操作static变量staticX
for (int i = 0; i < val; i++) {
staticX += 1;
}
}
}
经测试,发现运行instanceAccess()和staticAccess()方法的时间大约相同,但却比运行stackAccess()方法慢了2~3倍。因此我们对instanceAccess()、staticAccess()两个方法的代码作以下调整,以得到更快的性能:
public void instanceAccess(int val) {//访问和操作instance变量x
int tempX = x;
for (int i = 0; i < val; i++) {
tempX += 1;
}
x = tempX;
}
public void staticAccess(int val) {//访问和操作static变量staticX
int tempStaticX = staticX;
for (int i = 0; i < val; i++) {
tempStaticX += 1;
}
staticX = tempStaticX;
}
改善之处就是将instance和static变量放到循环之外,而用一个stack变量来完成多次局部运算,最后再将这个stack变量的值传回instance或static变量,从而提高了代码的性能。
注意对象的创建
String 是不可变的对象,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
例子1:
String conditions = "GROUPNO = '" + groupNo + "' AND TABLENAME = '" + tableName + "'";
改成
StringBuffer buff = new StringBuffer();
buff.append("GROUPNO = '");
buff.append(groupNo);
buff.append("' AND TABLENAME = '");
buff.append(tableName)
buff.append("'");
在循环体中注意对象的创建,尽量少创建新对象,以下data对象其实可以只创建一次。
例子2:
int len = 0;
FileInputStream fis = new FileInputStream("tt.data");
try{
while( len!=-1 ){
byte[] data = new byte[1024];
len = fis.read(data);
//...
}
}finally{
fis.close();
}
改成
int len = 0;
byte[] data = new byte[1024];
FileInputStream fis = new FileInputStream("tt.data");
try{
while( (len = fis.read(data))!=-1 ){
//...
}
}finally{
fis.close();
}
避免没必要的new,比如定义了个变量来引用已有的对象,那么这个定义的变量就不需要new。
例子3:
List<WbusinessCmain> wbusinessCmainClaimCancelList = new ArrayList<WbusinessCmain>(
0);
wbusinessCmainClaimCancelList = bpmCommonService
.getAllByBusinessNo(prpLclaim.getClaimNo(),
ClaimNode.REJECTUNDWRT.getNodeName());
改成
List<WbusinessCmain> wbusinessCmainClaimCancelList = null;
wbusinessCmainClaimCancelList = bpmCommonService
.getAllByBusinessNo(prpLclaim.getClaimNo(),
ClaimNode.REJECTUNDWRT.getNodeName());
循环条件中不用复杂表达式
在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。
例子:
for (int i = 0; i < vector.size (); i++){
//...
}
改成:
int size = vector.size ();
for (int i = 0; i < size; i++){
//...
}
释放资源
及时释放资源和保证资源释放,及时释放资源一般在一个方法中使用和释放资源。
例子1:
public static Properties loadProperties(String fileName)
throws IOException {
FileInputStream stream = new FileInputStream(fileName);
try {
Properties props = new Properties();
props.load(stream);
return props;
}
finally {
stream.close();
}
}
这个方法是用了FileInputStream资源,并在方法结束时调用 stream.close(); 释放了该资源。
保证释放资源,就是当你同时打开多个资源时,要保证每个资源都能释放掉。
例子2:
public void () throws SQLException {
Connection connOra = null;
Connection connDb2 = null;
try {
connOra = getConnection("ora");
connDb2 = getConnection("db2");
// Use connection
}
finally {
try {
if (connOra != null) {
connOra.close();
}
}
finally {
if (connDb2 != null) {
connDb2.close();
}
}
}
}
以上例子保证了,不管出现什么异常,connOra和connDb2的close方法都能执行到。
缩短有限资源的占用时间
比如数据库连接,我们在分配到连接后,尽量只做数据存取操作,并且尽可能减少操作次数。
比如:
int len = vec.size();
for(int i=0;i<len;i++){
conn.executeUpdate((String)vec.get(i));
}
String sql = endNode(node);
conn.executeUpdate(sql);
这段代码存在的问题:
循环执行sql语句;
执行了endNode业务方法;
正确的做法是把endNode方法放到获取连接前,把执行sql做成批量几次执行完(最好1次,但考虑到可能批量有长度限制)。
死锁例子
死锁产生的原因很简单。线程1锁住资源A等待资源B,线程2锁住资源B等待资源A,两个线程都在等待自己需要的资源 而这些资源被另外的线程锁住,这些线程你等我,我等你,谁也不愿意让出资源,这样死锁就产生了。举一个形象的例子2个人(2个线程)要过一个独木桥(资源),两人走到中间停下来等另外一个人让路,不幸的是没有人愿意让路,于是两人就无限期的等下去了。
public class DeadLockTest implements Runnable {
public boolean flag = true;
static Object res1 = new Object();
static Object res2 = new Object();
public void run() {
if(flag) {
/**//* 锁定资源res1 */
synchronized(res1) {
System.out.println("Resource 1 is locked. Waiting for Resource 2.");
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {}
/**//* 锁定资源res2 */
synchronized(res2) {
System.out.println("Complete.");
}
}
}
else {
/**//* 锁定资源res2 */
synchronized(res2) {
System.out.println("Resource 2 is locked. Waiting for Resource 1.");
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {}
/**//* 锁定资源res1 */
synchronized(res1) {
System.out.println("Complete.");
}
}
}
}
public static void main(String[] args) {
DeadLockTest r1 = new DeadLockTest();
DeadLockTest r2 = new DeadLockTest();
r2.flag = false;
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
运行结果:
Resource 1 is locked.
Waiting for Resource 2.
Resource 2 is locked.
Waiting for Resource 1.
。。。(死锁)
以上死锁可以通过规定访问锁资源的顺序来解决。
追踪程序效率点
一般我们使用一些工具来找出效率的关键点,在没工具的情况下可以使用最土的打时间日志方法。
比如使用jprofiler观察CPU数据如下:
从这个数据,可以找到各个方法调用次数和消耗的时间,很显然这个例子的Calendar.getInstance消耗了 70.9%的时间。我们的j2ee应用也可以使用这样的工具去找出这些效率点。
- 大小: 6 KB
分享到:
相关推荐
总之,理解并掌握Java垃圾回收机制对于编写高效、稳定的Java程序至关重要。通过实践和调整,我们可以有效地利用内存资源,提高应用的运行效率。在实际项目中,选择合适的垃圾回收器和调优策略是提升系统性能的关键。
Java代码自动生成工具是一种高效开发辅助软件,它能够根据预设的模板或规则,自动创建出符合特定规范的Java源代码。这样的工具极大地提升了开发效率,减少了程序员在编写重复性结构化代码上的时间,使他们可以更加...
这个名为"Java语言基础例子代码.rar"的压缩包提供了一系列基础Java编程的实例,旨在帮助初学者更好地理解和掌握Java编程的基本概念和操作。这些例子涵盖了数组、数学算法以及字符串处理等核心主题,对于学习Java的...
Java代码优化是一个持续的过程,它包含了许多细节和技巧,能够帮助开发者编写出更高效、更易于维护的代码。在这44条Java代码优化建议中,我们可以提炼出一些核心的知识点,为Java编程实践提供参考。 首先,关于为...
掌握InputStream、OutputStream、Reader、Writer及其子类,以及BufferedReader、PrintWriter等高级类,能让你编写出处理数据输入输出的高效代码。 6. **多线程**:Java提供了强大的多线程支持。学习Thread类、...
【Jocky混淆JAVA代码(保护你的JAVA项目)】...综上所述,Jocky提供了一种高效且灵活的Java代码保护方案,它简化了混淆过程,提高了代码的反编译难度,并且支持新语法的向后兼容,为Java开发者提供了一道有效的安全屏障。
在编程领域,多态(Polymorphism)是面向对象编程中的一个核心概念,它允许我们用统一的方式处理不同类型的对象,增强了代码的灵活性...在理解和掌握这些知识点后,开发者能够更好地设计和编写出高效、易于维护的代码。
【标题】"联通SGIP短信发送程序举例(java)" 涉及的知识点: 1. **SGIP协议**:SGIP(Short Message Gateway Interface Protocol)是中国联通制定的一种短信网关接口协议,用于短信中心(SMSC)与业务平台之间的通信...
2. 创建C3P0的数据源配置,可以使用XML或Java代码方式。这里以Java代码为例: ```java ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass("com.mysql.jdbc.Driver"); // 设置数据库...
这种方法被称为试除法,效率较高,但依然可以优化,如使用埃拉托斯特尼筛法来更高效地找到一定范围内的所有素数。 【程序3】是寻找水仙花数,即各位数字立方和等于原数的三位数。例如153就是一个水仙花数,因为1^3 ...
<br>举例说明:例如,本加密工具安装在c:\hideasoft\java_protect,执行加密后的CLASS文件的命令行如下: java -agentlib:c:\hideasoft\java_protect\hidea <您的CLASS类及参数> 应用场合 独立的应用...
通过上述示例代码和解释,我们了解了如何使用Java NIO的`Selector`类来实现高性能的网络编程。`Selector`能够帮助我们轻松管理大量的并发连接,提高程序的响应速度和效率。在未来开发中,掌握`Selector`的使用将会...
Java泛型是Java编程语言中的一个关键...通过深入理解并熟练运用以上知识点,开发者可以写出更加安全、高效且易于维护的Java代码。对于Java泛型的例子,可以通过运行和分析压缩包中的`generic`文件来加深理解和实践。
举例说明:例如,本加密工具安装在c:\lanswonsoft\java_protect,执行加密后的CLASS文件的命令行如下: java -agentlib:c:\lanswonsoft\java_protect\lanswon <您的CLASS类及参数> 应用场合 独立的应用程序...
总之,理解Java类的初始化顺序对于编写高效、可靠的代码至关重要。正确使用静态和非静态代码块可以帮助我们更好地控制对象的生命周期,从而优化程序性能。在涉及继承时,必须清楚地了解这些顺序,以便正确地处理父类...
1. **Java语言基础**:Java是一种面向对象的编程语言,具有平台无关性、安全性和高效性等特点。基础包括语法结构、数据类型、运算符、流程控制语句(如if-else、for、while)、类和对象等。 2. **面向对象编程(OOP...
- 1.3.2 ANDROID核心代码:Java是Android应用的主要开发语言,深入理解Java有助于开发高质量的Android应用。 - 1.3.3 大数据-HADOOP:Java在大数据处理领域也扮演着重要角色,例如Hadoop框架就是用Java实现的。 1.4...
- **1.4 JAVA开发场景举例 2:ANDROID 核心代码** 在Android开发中,Java编写应用程序的主要逻辑,包括UI设计、事件处理、网络通信等功能。 - **1.5 JAVA开发场景举例 3:大数据-HADOOP** 大数据处理领域,Java...
Java基础教程:动态代理与Java 8新特性 - AOP与动态代理的举例 在Java编程中,动态代理和Java 8的新特性是提升代码效率和可维护性的重要工具。本教程将深入探讨这两个概念,并通过实例来阐述它们在实际应用中的作用...