ZhipSoft.com
              冬去春來(lái)
                  鄭重聲明:本Blog純屬個(gè)人學(xué)習(xí)、工作需要,記錄相關(guān)資料。請(qǐng)不要發(fā)表任何有人身攻擊的言論,謝謝?。?/font>www.ZhipSoft.com
          posts - 94,comments - 149,trackbacks - 0

           J2EE中的優(yōu)化方案

          1.使用StringBuffer代替String

          String是用來(lái)存儲(chǔ)字符串常量的,如果要執(zhí)行“+”的操作,系統(tǒng)會(huì)生成一些臨時(shí)的對(duì)象,并對(duì)這些對(duì)象進(jìn)行管理,造成不必要的開(kāi)銷。

          如果字符串有連接的操作,替代的做法是用StringBuffer類的append方法。

          當(dāng)字符串的大小超過(guò)缺省16時(shí),代碼實(shí)現(xiàn)了容量的擴(kuò)充,為了避免對(duì)象的重新擴(kuò)展其容量,那么最好用StringBuffer sb=new StringBuffer(30)

          2.優(yōu)化循環(huán)體

          Vector vect = new Vector(1000);
          for( inti=0; i<vect.size(); i++){
           ...
          }

            for循環(huán)部分改寫(xiě)成:

          int size = vect.size();
          for( int i=0; i>size; i++){
           ...
          }

          如果size=1000,就避免了1000次的size()調(diào)用開(kāi)銷,避免了重復(fù)調(diào)用.

          3.對(duì)象的創(chuàng)建

          盡量少用new來(lái)初始化一個(gè)類的實(shí)例,當(dāng)一個(gè)對(duì)象是用new進(jìn)行初始化時(shí),其構(gòu)造函數(shù)鏈的所有構(gòu)造函數(shù)都被調(diào)用到,所以new操作符是很消耗系統(tǒng)資源的,new一個(gè)對(duì)象耗時(shí)往往是局部變量賦值耗時(shí)的上千倍。同時(shí),當(dāng)生成對(duì)象后,系統(tǒng)還要花時(shí)間進(jìn)行垃圾回收和處理。

          當(dāng)new創(chuàng)建對(duì)象不可避免時(shí),注意避免多次的使用new初始化一個(gè)對(duì)象。

          盡量在使用時(shí)再創(chuàng)建該對(duì)象。

          NewObject object = new NewObject();
          int value;
          if(i>0 )
          {
           value =object.getValue();
          }

            可以修改為:

          int value;
          if(i>0 )
          {
           NewObject object = new NewObject();
           Value =object.getValue();
          }

          4.慎用異常處理

            異常是Java的一種錯(cuò)誤處理機(jī)制,對(duì)程序來(lái)說(shuō)是非常有用的,但是異常對(duì)性能不利。拋出異常首先要?jiǎng)?chuàng)建一個(gè)新的對(duì)象,并進(jìn)行相關(guān)的處理,造成系統(tǒng)的開(kāi)銷,所以異常應(yīng)該用在錯(cuò)誤處理的情況,不應(yīng)該用來(lái)控制程序流程,流程盡量用while,if等處理。

          在不是很影響代碼健壯性的前提下,可以把幾個(gè)try/catch塊合成一個(gè)。

          討論:需要處理的異常處理和不需要處理的異常處理在捕捉異常類型上應(yīng)該采取什么策略。

          5.變量的使用

             盡量使用局部變量,調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧(Stack) 中,速度較快。其他變量,如靜態(tài)變量、實(shí)例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。

          盡量使用靜態(tài)變量,即加修飾符static,如果類中的變量不會(huì)隨他的實(shí)例而變化,就可以定義為靜態(tài)變量,從而使他所有的實(shí)例都共享這個(gè)變量。

          (但是靜態(tài)變量不能濫用,如果這個(gè)變量用的比較少而聲明成靜態(tài)變量,不僅效率不會(huì)提高,還會(huì)影響性能)

           

          6.I/O操作

              輸入/輸出(I/O)包括很多方面,我們知道,進(jìn)行I/O操作是很費(fèi)系統(tǒng)資源的。程序中應(yīng)該盡量少用I/O操作。使用時(shí)可以注意: . 合理控制輸出函數(shù)System.out.println()對(duì)于大多時(shí)候是有用的,特別是系統(tǒng)調(diào)試的時(shí)候,但也會(huì)產(chǎn)生大量的信息出現(xiàn)在控制臺(tái)和日志上,同時(shí)輸出時(shí),有序列化和同步的過(guò)程,造成了開(kāi)銷。

              特別是在發(fā)行版中,要合理的控制輸出,可以在項(xiàng)目開(kāi)發(fā)時(shí),設(shè)計(jì)好一個(gè)Debug的工具類,在該類中可以實(shí)現(xiàn)輸出開(kāi)關(guān),輸出的級(jí)別,根據(jù)不同的情況進(jìn)行不同的輸出的控制。

              我們?cè)谡{(diào)試程序的時(shí)候,我們喜歡用System.out.println()這樣的打印語(yǔ)句來(lái)跟蹤我們的錯(cuò)誤。但在程序發(fā)布的時(shí)候我們卻沒(méi)有把這樣的語(yǔ)句都刪除掉,在項(xiàng)目的運(yùn)行中,也會(huì)影響效能。

          7.使用緩存

            讀寫(xiě)內(nèi)存要比讀寫(xiě)文件要快很多,應(yīng)盡可能使用緩沖。

            盡可能使用帶有Buffer的類代替沒(méi)有Buffer的類,如可以用BufferedReader 代替Reader,用BufferedWriter代替Writer來(lái)進(jìn)行處理I/O操作。

          同樣可以用BufferedInputStream代替InputStream都可以獲得性能的提高。
           
          8.Servlet的效率問(wèn)題

            Servlet采用請(qǐng)求——響應(yīng)模式提供Web服務(wù),通過(guò)ServletResponse以及ServletRequest這兩個(gè)對(duì)象來(lái)輸出和接收用戶傳遞的參數(shù),在服務(wù)器端處理用戶的請(qǐng)求,根據(jù)請(qǐng)求訪問(wèn)數(shù)據(jù)庫(kù)、訪問(wèn)別的Servlet方法、調(diào)用EJB等等,然后將處理結(jié)果返回給客戶端。

            ·盡量不使用同步

          Servlet是多線程的,以處理不同的請(qǐng)求,基于前面同步的分析,如果有太多的同步就失去了多線程的優(yōu)勢(shì)了。

          同步大多數(shù)使用在一個(gè)完整的事務(wù)中,避免事務(wù)中多方操作而引起的數(shù)據(jù)不同步現(xiàn)象。能用邏輯控制的盡量的用邏輯控制。

            ·不用保存太多的信息在HttpSession中

            很多時(shí)候,存儲(chǔ)一些對(duì)象在HttpSession中是有必要的,可以加快系統(tǒng)的開(kāi)發(fā),如網(wǎng)上商店系統(tǒng)會(huì)把購(gòu)物車信息保存在該用戶的Session中,但當(dāng)存儲(chǔ)大量的信息或是大的對(duì)象在會(huì)話中是有害的,特別是當(dāng)系統(tǒng)中用戶的訪問(wèn)量很大,對(duì)內(nèi)存的需求就會(huì)很高。

          具體開(kāi)發(fā)時(shí),在這兩者之間應(yīng)作好權(quán)衡。

          我們?cè)趯?xiě)web應(yīng)用時(shí),經(jīng)常只需要request的地方而使用了session,這樣會(huì)是效率大大的降低的。但是我們用到了session,在項(xiàng)目的開(kāi)發(fā)中又不能很好的利用session,這樣對(duì)效率都是有影響的。比如說(shuō),我們把用戶信息放在了session中,但是我們有時(shí)候在判斷用戶是否登錄的時(shí)候,我們傾向去數(shù)據(jù)庫(kù)里查這個(gè)是否有這個(gè)用戶,又是用了request,但是這樣是沒(méi)有必要的,因?yàn)槲覀冎恍枰袛鄐ession就行了。如果并發(fā)數(shù)量比較大的時(shí)候,服務(wù)器的負(fù)載就會(huì)過(guò)重。

            ·清除Session

            通常情況,當(dāng)達(dá)到設(shè)定的超時(shí)時(shí)間時(shí),同時(shí)有些Session沒(méi)有了活動(dòng),服務(wù)器會(huì)釋放這些沒(méi)有活動(dòng)的Session,.. 不過(guò)這種情況下,特別是多用戶并訪時(shí),系統(tǒng)內(nèi)存要維護(hù)多個(gè)的無(wú)效Session。

            當(dāng)用戶退出時(shí),應(yīng)該手動(dòng)釋放,回收資源,實(shí)現(xiàn)如下:..

          HttpSession theSession = request.getSession();
          // 獲取當(dāng)前Session
          if(theSession != null){
           theSession.invalidate(); // 使該Session失效
          }

          9.數(shù)據(jù)庫(kù)的操作

          在J2EE開(kāi)發(fā)的應(yīng)用系統(tǒng)中,數(shù)據(jù)庫(kù)訪問(wèn)一般是個(gè)必備的環(huán)節(jié)。數(shù)據(jù)庫(kù)用來(lái)存儲(chǔ)業(yè)務(wù)數(shù)據(jù),供應(yīng)用程序訪問(wèn)。

            在Java技術(shù)的應(yīng)用體系中,應(yīng)用程序是通過(guò)JDBC(Java Database Connectivity)實(shí)現(xiàn)的接口來(lái)訪問(wèn)數(shù)據(jù)庫(kù)的,JDBC支持“建立連接、SQL語(yǔ)句查詢、處理結(jié)果”等基本功能。在應(yīng)用JDBC接口訪問(wèn)數(shù)據(jù)庫(kù)的過(guò)程中,只要根據(jù)規(guī)范來(lái)實(shí)現(xiàn),就可以達(dá)到要求的功能。

            但是,有些時(shí)候進(jìn)行數(shù)據(jù)查詢的效率著實(shí)讓開(kāi)發(fā)人員不如所愿,明明根據(jù)規(guī)范編寫(xiě)的程序,運(yùn)行效果卻很差,造成整個(gè)系統(tǒng)的執(zhí)行效率不高。

            ·使用速度快的JDBC驅(qū)動(dòng)

            JDBC API包括兩種實(shí)現(xiàn)接口形式,一種是純Java實(shí)現(xiàn)的驅(qū)動(dòng),一種利用ODBC驅(qū)動(dòng)和數(shù)據(jù)庫(kù)客戶端實(shí)現(xiàn),具體有四種驅(qū)動(dòng)模式并各有不同的應(yīng)用范圍,針對(duì)不同的應(yīng)用開(kāi)發(fā)要選擇合適的JDBC驅(qū)動(dòng),在同一個(gè)應(yīng)用系統(tǒng)中,如果選擇不同的JDBC驅(qū)動(dòng),在效率上會(huì)有差別。

          例如,有一個(gè)企業(yè)應(yīng)用系統(tǒng),不要求支持不同廠商的數(shù)據(jù)庫(kù),這時(shí)就可以選擇模式4的JDBC驅(qū)動(dòng),該驅(qū)動(dòng)一般由數(shù)據(jù)庫(kù)廠商實(shí)現(xiàn)的基于本地協(xié)議的驅(qū)動(dòng),直接調(diào)用數(shù)據(jù)庫(kù)管理系統(tǒng)使用的協(xié)議,減少了模式3中的中間層。

            ·使用JDBC連接池

            為了提高訪問(wèn)數(shù)據(jù)庫(kù)的性能,我們還可以使用JDBC 2.0的一些規(guī)范和特性,JDBC是占用資源的,在使用數(shù)據(jù)庫(kù)連接時(shí)可以使用連接池Connection Pooling,避免頻繁打開(kāi)、關(guān)閉Connection。而我們知道,獲取Connection是比較消耗系統(tǒng)資源的。

            Connection緩沖池是這樣工作的:當(dāng)一個(gè)應(yīng)用程序關(guān)閉一個(gè)數(shù)據(jù)庫(kù)連接時(shí),這個(gè)連接并不真正釋放而是被循環(huán)利用,建立連接是消耗較大的操作,循環(huán)利用連接可以顯著的提高性能,因?yàn)榭梢詼p少新連接的建立。

            一個(gè)通過(guò)DataSource獲取緩沖池獲得連接,并連接到一個(gè)CustomerDB數(shù)據(jù)源的代碼演示如下:

          Context ctx = new InitialContext();
          DataSource dataSource = (DataSource) ctx.lookup("jdbc/CustomerDB");
          Connection conn = dataSource.getConnection("password","username");

            ·緩存DataSource

            一個(gè)DataSource對(duì)象代表一個(gè)實(shí)際的數(shù)據(jù)源。這個(gè)數(shù)據(jù)源可以是從關(guān)系數(shù)據(jù)庫(kù)到表格形式的文件,完全依賴于它是怎樣實(shí)現(xiàn)的,一個(gè)數(shù)據(jù)源對(duì)象注冊(cè)到JNDI名字服務(wù)后,應(yīng)用程序就可以從JNDI服務(wù)器上取得該對(duì)象,并使用之和數(shù)據(jù)源建立連接。

            通過(guò)上面的例子,我們知道DataSource是從連接池獲得連接的一種方式,通過(guò)JNDI方式獲得,是占用資源的。

            為了避免再次的JNDI調(diào)用,可以系統(tǒng)中緩存要使用的DataSource。

            ·關(guān)閉所有使用的資源

            系統(tǒng)一般是并發(fā)的系統(tǒng),在每次申請(qǐng)和使用完資源后,應(yīng)該釋放供別人使用,數(shù)據(jù)庫(kù)資源每個(gè)模式的含義可以參考SUN JDBC的文檔,不同是比較寶貴的,使用完成后應(yīng)該保證徹底的釋放。

            請(qǐng)看下面的代碼段:

          Connection conn = null;
          Statement stmt = null;
          ResultSet rs = null;
          try {
           DataSource dataSource = getDataSource();
           // 取的DataSource的方法,實(shí)現(xiàn)略。
           conn = datasource.getConnection();
           stmt = conn.createStatement();
           rs = stmt.executeQuery("SELECT * FROM ...");
           ... // 其他處理
           rs.close();
           stmt.close();
           conn.close();
          }catch (SQLException ex) {
           ... // 錯(cuò)誤處理
          }

            粗看似乎沒(méi)有什么問(wèn)題,也有關(guān)閉相關(guān)如Connection等系統(tǒng)資源的代碼,但當(dāng)出現(xiàn)異常后,關(guān)閉資源的代碼可能并不被執(zhí)行,為保證資源的確實(shí)已被關(guān)閉,應(yīng)該把資源關(guān)閉的代碼放到finally塊:

          Connection conn = null;
          Statement stmt = null;
          ResultSet rs = null;
          try {
           DataSource dataSource = getDataSource();
           // 取的DataSource的方法,實(shí)現(xiàn)略。
           conn = datasource.getConnection();
           stmt = conn.createStatement();
           rs = stmt.executeQuery("SELECT * FROM ...");

           ... // 其他處理
          }catch (SQLException ex) {
           ... // 錯(cuò)誤處理

          }finally{
           if (rs!=null) {
            try {
             rs.close(); // 關(guān)閉ResultSet}
            catch (SQLException ex) {
             ... // 錯(cuò)誤處理
            }
           }

           if (stmt!=null){
            try {
             stmt.close(); // 關(guān)閉Statement}
            catch (SQLException ex) {
             ... // 錯(cuò)誤處理
            }
           }
           if (conn!=null){
            try {
             conn.close(); // 關(guān)閉Connection}
            catch (SQLException ex) {
             ... // 錯(cuò)誤處理
            }
           }
          }

            ·大型數(shù)據(jù)量處理

            當(dāng)我們?cè)谧x取諸如數(shù)據(jù)列表、報(bào)表等大量數(shù)據(jù)時(shí),可以發(fā)現(xiàn)使用EJB的方法是非常慢的,這時(shí)可以使用直接訪問(wèn)數(shù)據(jù)庫(kù)的方法,用SQL直接存取數(shù)據(jù),從而消除EJB的經(jīng)常開(kāi)支(例如遠(yuǎn)程方法調(diào)用、事務(wù)管理和數(shù)據(jù)序列化,對(duì)象的構(gòu)造等)。

            ·緩存經(jīng)常使用的數(shù)據(jù)

            對(duì)于構(gòu)建的業(yè)務(wù)系統(tǒng),如果有些數(shù)據(jù)要經(jīng)常要從數(shù)據(jù)庫(kù)中讀取,同時(shí),這些數(shù)據(jù)又不經(jīng)常變化,這些數(shù)據(jù)就可以在系統(tǒng)中緩存起來(lái),使用時(shí)直接讀取緩存,而不用頻繁的訪問(wèn)數(shù)據(jù)庫(kù)讀取數(shù)據(jù)。

            緩存工作可以在系統(tǒng)初始化時(shí)一次性讀取數(shù)據(jù),特別是一些只讀的數(shù)據(jù),當(dāng)數(shù)據(jù)更新時(shí)更新數(shù)據(jù)庫(kù)內(nèi)容,同時(shí)更新緩存的數(shù)據(jù)值。

          一個(gè)例子是,在一套企業(yè)應(yīng)用系統(tǒng)中,企業(yè)的信息數(shù)據(jù)(如企業(yè)的名稱)在多個(gè)業(yè)務(wù)應(yīng)用模塊中使用,這時(shí)就可以把這些數(shù)據(jù)緩存起來(lái),需要時(shí)直接讀取緩存的企業(yè)信息數(shù)據(jù)。

          我們經(jīng)常使用Hibernate這樣的持久數(shù)據(jù)層的框架,就很好的利用了緩存的作用,所以在一定程度上彌補(bǔ)了封裝而帶來(lái)的效率丟失問(wèn)題。但是在使用緩存的時(shí)候應(yīng)該注意,因?yàn)樵L問(wèn)的內(nèi)存數(shù)據(jù)而不是真實(shí)的數(shù)據(jù)庫(kù)數(shù)據(jù),所以會(huì)出現(xiàn)臟讀的情況。同時(shí)也并不是所有的東西都應(yīng)該放在緩存中,不經(jīng)常用到的我們就沒(méi)有必要放在緩存中。有時(shí)候我們配合x(chóng)ml文件來(lái)使用,也不失一種好的方法。

           

          一般意義上說(shuō),參與系統(tǒng)運(yùn)行的代碼都會(huì)對(duì)性能產(chǎn)生影響,實(shí)際應(yīng)用中應(yīng)該養(yǎng)成良好的編程規(guī)范、編寫(xiě)高質(zhì)量的代碼,當(dāng)系統(tǒng)性能出現(xiàn)問(wèn)題時(shí),要找到主要影響性能的瓶頸所在,然后集中精力優(yōu)化這些代碼,能達(dá)到事半功倍的效果。

            J2EE性能的優(yōu)化包括很多方面的,要達(dá)到一個(gè)性能優(yōu)良的系統(tǒng),除了關(guān)注代碼之外,還應(yīng)該根據(jù)系統(tǒng)實(shí)際的運(yùn)行情況,從服務(wù)器軟硬件環(huán)境、集群技術(shù)、系統(tǒng)構(gòu)架設(shè)計(jì)、系統(tǒng)部署環(huán)境、數(shù)據(jù)結(jié)構(gòu)、算法設(shè)計(jì)等方面綜合考慮。

           



                  本Blog純屬個(gè)人學(xué)習(xí)、工作需要,記錄相關(guān)資料。請(qǐng)不要發(fā)表任何有人身攻擊的言論,謝謝! www.zhipsoft.cn
          posted on 2007-06-12 08:49 ZhipSoft 閱讀(610) 評(píng)論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 巨鹿县| 湘乡市| 西充县| 百色市| 万年县| 佛山市| 隆子县| 嘉禾县| 忻城县| 万安县| 邯郸县| 达孜县| 岳阳县| 岫岩| 日土县| 抚州市| 久治县| 安义县| 丁青县| 普陀区| 海伦市| 溆浦县| 巴塘县| 内丘县| 杭锦旗| 德州市| 微山县| 株洲市| 宁阳县| 肥城市| 黑河市| 呼伦贝尔市| 阳信县| 常熟市| 辽阳县| 康乐县| 新晃| 云浮市| 枣强县| 福贡县| 成武县|