java

位置:IT落伍者 >> java >> 浏览文章

一个开发实际项目中对 Java 性能提高的体会


发布日期:2021年05月30日
 
一个开发实际项目中对 Java 性能提高的体会

在开发的期间系统在运行的时候出现了一些问题现将我的问题解决方法做一个小结供以后作项目的参考并请大家不吝指教

问题

Resin 的数据库连接数目在程序运行中不断增长最后连接数目超过最大数导致Resin服务关闭

原因

在操作完数据库后没有关闭数据库连接或者是返回结果集(Resultset)而无法在jsp中关闭数据库连接

解决方法

. 在操作完数据库要关闭数据库连接

. 尽量不要返回结果集Resultset 可以返回Vector(一个字段)Hashtable(多个字段)这样可以在javabean中关闭数据库

. 如果javabean中返回的是结果集(Resultset)也可以在javaBean中写一个connectDB(连接数据库)closeDB(关闭数据库)的方法然后jsp里面调用connectDB()建立数据库连接同时就可以对数据库进行操作了操作数据库完毕可以通过closeDB() 来关闭数据库

关闭连接时尽量使用connclose()rsclose()而不要另外写方法去关闭它如调用DBcloseConnection(conn)等等这样其实对性能有一定影响因为该性能经过了我对单个文件的测试

关闭连接时请按顺序进行如rsclose()stmtclose()nnclose()

问题

在运行某一个jsp 程序的时候Resin 的内存陡然增长而且居高不下最终导致Resin 内存不足甚至当机

原因

过度使用内存

解决方法

. 由于数据量比较大在对字符串进行操作的时候使用 + 进行字符串连接

相信大家对String都非常熟悉我们也经常要用它来做字符串的连接什么的例如

String a =b+c file://bc 都是String

但是在实际的编译中却是这样

String a=new StringBuffer()append(b)append(c)toString() 显然在一个简单的语句中却意外的多生成了个对象

StringBuffer()

toString返回的一个String

我们比较一下这两段程序的性能

程序片断一

StringBuffer s=new StringBuffer();

long start = SystemcurrentTimeMillis();

for (int i=;i<;i++){

s+=a;

}

long stop = SystemcurrentTimeMillis();

Systemoutprintln(stopstart);

程序片断二

StringBuffer s=new StringBuffer();//

long start=SystemcurrentTimeMillis();

for (int i=;i<;i++){

sappend(a);

}

long stop=SystemcurrentTimeMillis();

Systemoutprintln(stopstart);

比较一下结果差距很明显

至于为什么String的连接这么做因为String无法直接改变其长度而必须采用StringBuffer的用法

因此建议使用StringBuffer 的append 方法来进行字符串相连

.在解决这个问题的时候我也尝试使用上面的方法效果并不是很明显(消耗内存上)后来在显示大量数据的时候避免字符串相连的步骤而直接使用outprintln()直接输出

问题Java并不阻止程序占用过多的内存当对象向堆所请求的内存不足时垃圾收集器(Garbage Collector)就会自动启动释放那些引用数为零的对象所占用的内存Java也不会自动释放无用的对象的引用如果程序忘记释放指向对象的引用则程序运行时的内存随着时间的推移而增加发生所谓内存洩漏(memory leaks)创建对象不但消耗CPU的时间和内存同时为释放对象内存JVM需不停地启动垃圾收集器(Garbage Collector)这也会消耗大量的CPU时间

解决方法 由于在运行一段时间jsp程序后Resin 的内存会有一个缓慢的增长这样也会导致内存溢出为了避免这总现象的出现最终的解决方法是 编写一个servlet程序在启动服务器的时候启动一个这个servlet每隔分钟运行在服务器端运行一次来定时回收内存

问题

log文件里面的调试信息没有注释去掉

解决方法

在程序通过后尽量把调试的信息注释去掉

同时在捕捉错误的时候要写明程序名称方便查找

问题

改善性能提高速度

具体实例

我们再来看一个有关Vector类的代码片段

for(int I=; I<vsize(); I++) { Systemoutprintln( vget(I)getClass()toString()); }

如果v包含个元素这个代码片段将调用vsize()方法虽然size方法是一个简单的方法但它仍旧需要一次方法调用的开销至少JVM需要为它配置以及清除堆栈环境在这里for循环内部的代码不会以任何方式修改Vector类型对象v的大小因此上面的代码最好改写成下面这种形式

int size = vsize(); for(int I=; I<size; I++) { Systemoutprintln( vget(I)getClass()toString()); }

虽然这是一个简单的改动但它仍旧赢得了性能毕竟每一个CPU周期都是宝贵的

问题

在 jsp 文件里面 不要写 <%@ page import=javalang* %>

因为java 不需要引入此包就可以引用里面的类文件

问题

使用vector+hashtable 一次返回查询结果resulset

解决方法 记录集将一条记录放到一个hashtable里面然后把它再

添加到vector里面循环记录下结果集返回vector

具体见后面的java文件的部分代码(不包扩数据库的连接和关闭)

package pany;

/********************************************

***** 说明

***** 记录集一条记录用放到一个hashtable里面然后把它再

放到vector里面循环记录下结果集返回vector

*********************************************/

import javaio*;

import javasql*;

import javautil*;

import javatext*;

public class hashtable_vector_rs

{

/**/

/* 函数名称 getMultiRowInfo

/* 功能描述 返回记录集放到Hashtable里面

/* 参数 sql 语句字段个数

/* 返回值: 成功htable 失败null

/**/

public Vector ListResult(String sqlStatementint num)

{

Vector ListRs=new Vector();

try

{

connectDB();

rs=stmtexecuteQuery(sqlStatement);

//判断字段数据类型

//date型 返回

//int型 返回

//bigint型 返回

//String型 返回

//(char 型)返回

int t = ;

rsmd = rsgetMetaData();

int ColumnCount=;

if(num>)

ColumnCount = num;

else

ColumnCount = rsmdgetColumnCount();

while(rsnext())

{

Hashtable htable =new Hashtable();

for (int i = ; i <= ColumnCount; i++)

{

t=rsmdgetColumnType(i);

Systemoutprintln(i=+i+t=+t+name=+rsmdgetColumnName(i));

if(t==||t==||t==)

{

if(rsgetString(i)==null|| rsgetString(i)equals())

htableput(rsmdgetColumnName(i));

else

htableput(rsmdgetColumnName(i)rsgetString(i));

}

else if(t==)

{

htableput(rsmdgetColumnName(i)rsgetDate(i)toString());

}

else if(t==||t==)

{

htableput(rsmdgetColumnName(i)IntegertoString(rsgetInt(i)));

}

}

ListRsadd(htable);

}//e

return ListRs;

}

catch(Exception listError)

{

Systemoutprintln(数据库操作失败!+listError);

return null;

}

finally

{

try

{

closeDB();

}

catch(Exception closeErr)

{

Systemoutprintln(关闭数据库出错+closeErr);

}

}

}

}

问题:

jsp的程序也有设计的不够合理的地方

例如选择一个下拉框提交一次列出所选的数据选择另外一个下拉框再次提交再次列出所选的数据

解决方法

尽量一次把条件选择完毕然后列出所选择的数据并且在数据多的时候尽量使用翻页减少运行时间

问题

性能优化尽量使用PreparedStatement

解决方法

PreparedStatement 对象和使用的普通的 Statement 对象有两点不同

第一 它们是为了性能更快而由 JDBC 驱动程序或数据库编译(预编译)的

第二 它们接受一个或多个动态输入参数称为 IN 参数这两点让 PreparedStatement 对象适用于重复的 SQL 操作其中操作基本上都是一样的只有微小的差异(如数据载入)要让 SQL 语句在使用前预备好在 PreparedStatement 对象创建时必须将 SQL 传送到 JDBC 驱动程序而不是在其执行时才传送

IN 参数用 SQL String 中的 ? 占位符表示在 PreparedStatement 能够成功地执行前还必须调用 PreparedStatement 对象的 se

上一篇:java设计模式之Mediator

下一篇:Java 程序中的多线程(四)