熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

一個開發實際項目中對 Java 性能提高的體會

2013-11-23 19:49:05  來源: 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
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27504.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.