Java性能優(yōu)化【技巧】集錦_第1頁
Java性能優(yōu)化【技巧】集錦_第2頁
Java性能優(yōu)化【技巧】集錦_第3頁
Java性能優(yōu)化【技巧】集錦_第4頁
Java性能優(yōu)化【技巧】集錦_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、 Java性能優(yōu)化技巧集錦=提綱:=一、通用篇1.1 不用new關鍵詞創(chuàng)建類的實例1.2 使用非阻塞 I/O1.3 慎用異常1.4 不要重復初始化變量1.5 盡量指定類的final修飾符 1.6 盡量使用局部變量1.7 乘法和除法 1.8 盡量重用對象。二、J2EE篇2.1 使用緩沖標記2.2 始終通過會話Bean訪問實體Bean2.3 選擇合適的引用機制2.4 在部署描述器中設置只讀屬性2.5 緩沖對EJB Home的訪問2.6 為EJB實現(xiàn)本地接口2.7 生成主鍵2.8 及時清除不再需要的會話2.9 在JSP頁面中關閉無用的會話2.10 Servlet與內(nèi)存使用2.11 HTTP Keep

2、-Alive2.12 JDBC與Unicode2.13 JDBC與I/O2.14 內(nèi)存數(shù)據(jù)庫三、GUI篇 3.1 用JAR壓縮類文件3.2 提示Applet裝入進程3.3 在畫出圖形之前預先裝入它3.4 覆蓋update方法3.5 延遲重畫操作3.6 使用雙緩沖區(qū)3.7 使用BufferedImage3.8 使用VolatileImage3.9 使用Window Blitting四、JavaScript性能優(yōu)化 1. 使用局部變量避免使用全局變2. 避免使用with3. 遍歷nodelist的方式4. 別用那么多個var,一個加逗號就搞定了5. innerHTML是最好的選擇6. ie的rem

3、oveChild不好用7. 為多個同級元素綁定事件時,不用為每個都綁定,為他們的父級綁定就行了8. 盡量用原生的方法,因為原生的都是用c/c+編譯而成的他們執(zhí)行的要比用js寫的方法快多了9. appendChild用的多時一定要用docuemntfragment10. if else用的=3個了,那用switch吧,好閱讀,性能好11. if=3,別用if了,用3元表達式吧12. if=1,if改&13. 元素位置,while()offsetParent14. 正則的查找沒有indexOf快15. 設置某個元素的style時用cssText簡單些16. new 時,沒有參數(shù)時函數(shù)名后邊的括號可

4、以去了五、其他=正文:=一、通用篇“通用篇”討論的問題適合于大多數(shù)Java應用。1.1 不用new關鍵詞創(chuàng)建類的實例用new關鍵詞創(chuàng)建類的實例時,構造函數(shù)鏈中的所有構造函數(shù)都會被自動調(diào)用。但如果一個對象實現(xiàn)了Cloneable接口,我們可以調(diào)用它的clone()方法。clone()方法不會調(diào)用任何類構造函數(shù)。在使用設計模式(Design Pattern)的場合,如果用Factory模式創(chuàng)建對象,則改用clone()方法創(chuàng)建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現(xiàn):public static Credit getNewCredit() return new Credit

5、(); 改進后的代碼使用clone()方法,如下所示:private static Credit BaseCredit = new Credit();public static Credit getNewCredit() return (Credit) BaseCredit.clone(); 上面的思路對于數(shù)組處理同樣很有用。1.2 使用非阻塞I/O版本較低的JDK不支持非阻塞I/O API。為避免I/O阻塞,一些應用采用了創(chuàng)建大量線程的辦法(在較好的情況下,會使用一個緩沖池)。這種技術可以在許多必須支持并發(fā)I/O流的應用中見到,如Web服務器、報價和拍賣應用等。然而,創(chuàng)建Java線程需要相當

6、可觀的開銷。JDK 1.4引入了非阻塞的I/O庫(java.nio)。如果應用要求使用版本較早的JDK,在這里有一個支持非阻塞I/O的軟件包。請參見Sun中國網(wǎng)站的調(diào)整Java的I/O性能。輸入和輸出包括很多方面,但涉及最多的是對硬盤,網(wǎng)絡或數(shù)據(jù)庫的讀寫操作。對于讀寫操作,又分為有緩存和沒有緩存的;對于數(shù)據(jù)庫的操作,又可以有多種類型的JDBC驅動器可以選擇。但無論怎樣,都會給程序的性能帶來影響。因此,需要注意如下幾點:(1) 使用輸入輸出緩沖盡可能的多使用緩存。但如果要經(jīng)常對緩存進行刷新(flush),則建議不要使用緩存。(2) 輸出流(Output Stream)和Unicode字符串當時用

7、Output Stream和Unicode字符串時,Write類的開銷比較大。因為它要實現(xiàn)Unicode到字節(jié)(byte)的轉換.因此,如果可能的話,在使用Write類之前就實現(xiàn)轉換或用OutputStream類代替Writer類來使用。(3) 當需序列化時使用transient當序列化一個類或對象時,對于那些原子類型(atomic)或可以重建的原素要表識為transient類型。這樣就不用每一次都進行序列化。如果這些序列化的對象要在網(wǎng)絡上傳輸,這一小小的改變對性能會有很大的提高。(4) 使用高速緩存(Cache)對于那些經(jīng)常要使用而又不大變化的對象或數(shù)據(jù),可以把它存儲在高速緩存中。這樣就可以

8、提高訪問的速度。這一點對于從數(shù)據(jù)庫中返回的結果集尤其重要。(5) 使用速度快的JDBC驅動器(Driver)JAVA對訪問數(shù)據(jù)庫提供了四種方法。這其中有兩種是JDBC驅動器。一種是用JAVA外包的本地驅動器;另一種是完全的JAVA驅動器。具體要使用哪一種得根據(jù)JAVA布署的環(huán)境和應用程序本身來定。1.3 慎用異常異常對性能不利。拋出異常首先要創(chuàng)建一個新的對象。Throwable接口的構造函數(shù)調(diào)用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調(diào)用跟蹤信息。只要有異常被拋出,VM就必須調(diào)整調(diào)用堆棧,因為在處理過程中創(chuàng)建了一

9、個新的對象。異常只能用于錯誤處理,不應該用來控制程序流程。JAVA語言中提供了try/catch來發(fā)方便用戶捕捉異常,進行異常的處理。但是如果使用不當,也會給JAVA程序的性能帶來影響。因此,要注意以下兩點。(1) 避免對應用程序的邏輯使用try/catch如果可以用if,while等邏輯語句來處理,那么就盡可能的不用try/catch語句(2) 重用異常在必須要進行異常的處理時,要盡可能的重用已經(jīng)存在的異常對象。因為在異常的處理中,生成一個異常對象要消耗掉大部分的時間。1.4 不要重復初始化變量默認情況下,調(diào)用類的構造函數(shù)時, Java會把變量初始化成確定的值:所有的對象被設置成null,整

10、數(shù)變量(byte、short、int、long)設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關鍵詞創(chuàng)建一個對象時,構造函數(shù)鏈中的所有構造函數(shù)都會被自動調(diào)用。1.5 盡量指定類的final修飾符帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內(nèi)聯(lián)(inline)所有的fina

11、l方法(這和具體的編譯器實現(xiàn)有關)。此舉能夠使性能平均提高50%。1.6 盡量使用局部變量調(diào)用方法時傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時變量都保存在棧(Stack)中,速度較快。其他變量,如靜態(tài)變量、實例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。另外,依賴于具體的編譯器/JVM,局部變量還可能得到進一步優(yōu)化。請參見盡可能使用堆棧變量。1.7 乘法和除法考慮下面的代碼:for (val = 0; val 。該指令在編譯時引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合并成一個文件。被引用的外部資源在編譯時就確定,比運行時才確定資源更高效。include 動作:例如。該動作引

12、入指定頁面執(zhí)行后生成的結果。由于它在運行時完成,因此對輸出結果的控制更加靈活。但時,只有當被引用的內(nèi)容頻繁地改變時,或者在對主頁面的請求沒有出現(xiàn)之前,被引用的頁面無法確定時,使用 include動作才合算。2.4 在部署描述器中設置只讀屬性實體Bean的部署描述器允許把所有get方法設置成“只讀”。當某個事務單元的工作只包含執(zhí)行讀取操作的方法時,設置只讀屬性有利于提高性能,因為容器不必再執(zhí)行存儲操作。2.5 緩沖對EJB Home的訪問EJB Home 接口通過JNDI名稱查找獲得。這個操作需要相當可觀的開銷。JNDI查找最好放入Servlet的init()方法里面。如果應用中多處頻繁地出現(xiàn)

13、EJB訪問,最好創(chuàng)建一個EJBHomeCache類。EJBHomeCache類一般應該作為singleton實現(xiàn)。2.6 為EJB實現(xiàn)本地接口本地接口是EJB 2.0規(guī)范新增的內(nèi)容,它使得Bean能夠避免遠程調(diào)用的開銷。請考慮下面的代碼。PayBeanHome home = (PayBeanHome) javax.rmi.PortableRemoteObject.narrow (ctx.lookup (PayBeanHome), PayBeanHome.class); PayBean bean = (PayBean) javax.rmi.PortableRemoteObject.narrow

14、(home.create(), PayBean.class); 第一個語句表示我們要尋找Bean的Home接口。這個查找通過JNDI進行,它是一個RMI調(diào)用。然后,我們定位遠程對象,返回代理引用,這也是一個RMI調(diào)用。第二個語句示范了如何創(chuàng)建一個實例,涉及了創(chuàng)建IIOP請求并在網(wǎng)絡上傳輸請求的 stub程序,它也是一個RMI調(diào)用。要實現(xiàn)本地接口,我們必須作如下修改:方法不能再拋出java.rmi.RemoteException異常,包括從RemoteException派生的異常,比如 TransactionRequiredException、TransactionRolledBackExcep

15、tion和 NoSuchObjectException。EJB提供了等價的本地異常,如TransactionRequiredLocalException、 TransactionRolledBackLocalException和NoSuchObjectLocalException。所有數(shù)據(jù)和返回值都通過引用的方式傳遞,而不是傳遞值。本地接口必須在EJB部署的機器上使用。簡而言之,客戶程序和提供服務的組件必須在同一個JVM上運行。如果Bean實現(xiàn)了本地接口,則其引用不可串行化。請參見用本地引用提高EJB訪問效率。2.7 生成主鍵在EJB之內(nèi)生成主鍵有許多途徑,下面分析了幾種常見的辦法以及它們的特

16、點。利用數(shù)據(jù)庫內(nèi)建的標識機制(SQL Server的IDENTITY或Oracle的SEQUENCE)。這種方法的缺點是EJB可移植性差。由實體Bean自己計算主鍵值(比如做增量操作)。它的缺點是要求事務可串行化,而且速度也較慢。利用NTP之類的時鐘服務。這要求有面向特定平臺的本地代碼,從而把Bean固定到了特定的OS之上。另外,它還導致了這樣一種可能,即在多CPU的服務器上,同一個毫秒之內(nèi)生成了兩個主鍵。借鑒Microsoft的思路,在Bean中創(chuàng)建一個GUID。然而,如果不求助于JNI,Java不能確定網(wǎng)卡的MAC地址;如果使用JNI,則程序就要依賴于特定的OS。還有其他幾種辦法,但這些辦

17、法同樣都有各自的局限。似乎只有一個答案比較理想:結合運用RMI和JNDI。先通過RMI注冊把RMI遠程對象綁定到JNDI樹??蛻舫绦蛲ㄟ^JNDI進行查找。下面是一個例子:public class keyGenerator extends UnicastRemoteObject implements Remote private static long KeyValue = System.currentTimeMillis(); public static synchronized long getKey() throws RemoteException return KeyValue+; 2.

18、8 及時清除不再需要的會話為了清除不再活動的會話,許多應用服務器都有默認的會話超時時間,一般為30分鐘。當應用服務器需要保存更多會話時,如果內(nèi)存容量不足,操作系統(tǒng)會把部分內(nèi)存數(shù)據(jù)轉移到磁盤,應用服務器也可能根據(jù)“最近最頻繁使用”(Most Recently Used)算法把部分不活躍的會話轉儲到磁盤,甚至可能拋出“內(nèi)存不足”異常。在大規(guī)模系統(tǒng)中,串行化會話的代價是很昂貴的。當會話不再需要時,應當及時調(diào)用HttpSession.invalidate()方法清除會話。 HttpSession.invalidate()方法通常可以在應用的退出頁面調(diào)用。2.9 在JSP頁面中關閉無用的會話對于那些無需

19、跟蹤會話狀態(tài)的頁面,關閉自動創(chuàng)建的會話可以節(jié)省一些資源。使用如下page指令: 2.10 Servlet與內(nèi)存使用許多開發(fā)者隨意地把大量信息保存到用戶會話之中。一些時候,保存在會話中的對象沒有及時地被垃圾回收機制回收。從性能上看,典型的癥狀是用戶感到系統(tǒng)周期性地變慢,卻又不能把原因歸于任何一個具體的組件。如果監(jiān)視JVM的堆空間,它的表現(xiàn)是內(nèi)存占用不正常地大起大落。解決這類內(nèi)存問題主要有二種辦法。第一種辦法是,在所有作用范圍為會話的Bean中實現(xiàn)HttpSessionBindingListener接口。這樣,只要實現(xiàn)valueUnbound()方法,就可以顯式地釋放Bean使用的資源。另外一種辦

20、法就是盡快地把會話作廢。大多數(shù)應用服務器都有設置會話作廢間隔時間的選項。另外,也可以用編程的方式調(diào)用會話的 setMaxInactiveInterval()方法,該方法用來設定在作廢會話之前,Servlet容器允許的客戶請求的最大間隔時間,以秒計。2.11 HTTP Keep-AliveKeep -Alive功能使客戶端到服務器端的連接持續(xù)有效,當出現(xiàn)對服務器的后繼請求時,Keep-Alive功能避免了建立或者重新建立連接。市場上的大部分 Web服務器,包括iPlanet、IIS和Apache,都支持HTTP Keep-Alive。對于提供靜態(tài)內(nèi)容的網(wǎng)站來說,這個功能通常很有用。但是,對于負擔

21、較重的網(wǎng)站來說,這里存在另外一個問題:雖然為客戶保留打開的連接有一定的好處,但它同樣影響了性能,因為在處理暫停期間,本來可以釋放的資源仍舊被占用。當Web服務器和應用服務器在同一臺機器上運行時,Keep-Alive功能對資源利用的影響尤其突出。2.12 JDBC與Unicode想必你已經(jīng)了解一些使用JDBC時提高性能的措施,比如利用連接池、正確地選擇存儲過程和直接執(zhí)行的SQL、從結果集刪除多余的列、預先編譯SQL語句,等等。除了這些顯而易見的選擇之外,另一個提高性能的好選擇可能就是把所有的字符數(shù)據(jù)都保存為Unicode(代碼頁13488)。Java以Unicode形式處理所有數(shù)據(jù),因此,數(shù)據(jù)庫

22、驅動程序不必再執(zhí)行轉換過程。但應該記?。喝绻捎眠@種方式,數(shù)據(jù)庫會變得更大,因為每個Unicode字符需要2個字節(jié)存儲空間。另外,如果有其他非Unicode的程序訪問數(shù)據(jù)庫,性能問題仍舊會出現(xiàn),因為這時數(shù)據(jù)庫驅動程序仍舊必須執(zhí)行轉換過程。2.13 JDBC與I/O如果應用程序需要訪問一個規(guī)模很大的數(shù)據(jù)集,則應當考慮使用塊提取方式。默認情況下,JDBC每次提取32行數(shù)據(jù)。舉例來說,假設我們要遍歷一個5000行的記錄集,JDBC必須調(diào)用數(shù)據(jù)庫157次才能提取到全部數(shù)據(jù)。如果把塊大小改成512,則調(diào)用數(shù)據(jù)庫的次數(shù)將減少到10次。在一些情形下這種技術無效。例如,如果使用可滾動的記錄集,或者在查詢中指定

23、了FOR UPDATE,則塊操作方式不再有效。2.14 內(nèi)存數(shù)據(jù)庫許多應用需要以用戶為單位在會話對象中保存相當數(shù)量的數(shù)據(jù),典型的應用如購物籃和目錄等。由于這類數(shù)據(jù)可以按照行/列的形式組織,因此,許多應用創(chuàng)建了龐大的Vector或HashMap。在會話中保存這類數(shù)據(jù)極大地限制了應用的可伸縮性,因為服務器擁有的內(nèi)存至少必須達到每個會話占用的內(nèi)存數(shù)量乘以并發(fā)用戶最大數(shù)量,它不僅使服務器價格昂貴,而且垃圾收集的時間間隔也可能延長到難以忍受的程度。一些人把購物籃/目錄功能轉移到數(shù)據(jù)庫層,在一定程度上提高了可伸縮性。然而,把這部分功能放到數(shù)據(jù)庫層也存在問題,且問題的根源與大多數(shù)關系數(shù)據(jù)庫系統(tǒng)的體系結構有關

24、。對于關系數(shù)據(jù)庫來說,運行時的重要原則之一是確保所有的寫入操作穩(wěn)定、可靠,因而,所有的性能問題都與物理上把數(shù)據(jù)寫入磁盤的能力有關。關系數(shù)據(jù)庫力圖減少I/O操作,特別是對于讀操作,但實現(xiàn)該目標的主要途徑只是執(zhí)行一套實現(xiàn)緩沖機制的復雜算法,而這正是數(shù)據(jù)庫層第一號性能瓶頸通??偸荂PU的主要原因。一種替代傳統(tǒng)關系數(shù)據(jù)庫的方案是,使用在內(nèi)存中運行的數(shù)據(jù)庫(In-memory Database),例如TimesTen。內(nèi)存數(shù)據(jù)庫的出發(fā)點是允許數(shù)據(jù)臨時地寫入,但這些數(shù)據(jù)不必永久地保存到磁盤上,所有的操作都在內(nèi)存中進行。這樣,內(nèi)存數(shù)據(jù)庫不需要復雜的算法來減少I/O操作,而且可以采用比較簡單的加鎖機制,因而速

25、度很快。三、GUI篇這一部分介紹的內(nèi)容適合于圖形用戶界面的應用(Applet和普通應用),要用到AWT或Swing。3.1 用JAR壓縮類文件Java檔案文件(JAR文件)是根據(jù) JavaBean標準壓縮的文件,是發(fā)布JavaBean組件的主要方式和推薦方式。JAR檔案有助于減少文件體積,縮短下載時間。例如,它有助于 Applet提高啟動速度。一個JAR文件可以包含一個或者多個相關的Bean以及支持文件,比如圖形、聲音、HTML和其他資源。要在HTML/JSP文件中指定JAR文件,只需在Applet標記中加入ARCHIVE = name.jar聲明。請參見使用檔案文件提高 applet 的加載

26、速度。3.2 提示Applet裝入進程你是否看到過使用Applet的網(wǎng)站,注意到在應該運行Applet的地方出現(xiàn)了一個占位符?當Applet的下載時間較長時,會發(fā)生什么事情?最大的可能就是用戶掉頭離去。在這種情況下,顯示一個Applet正在下載的信息無疑有助于鼓勵用戶繼續(xù)等待。下面我們來看看一種具體的實現(xiàn)方法。首先創(chuàng)建一個很小的Applet,該Applet負責在后臺下載正式的Applet:import java.applet.Applet; import java.applet.AppletStub;import java.awt.Label;import java.awt.Graphics;

27、 import java.awt.GridLayout; public class PreLoader extends Applet implements Runnable, AppletStub String largeAppletName; Label label; public void init () / 要求裝載的正式Applet largeAppletName = getParameter (applet); / “請稍等”提示信息 label = new Label(請稍等. + largeAppletName); add(label); public void run() tr

28、y / 獲得待裝載Applet的類 Class largeAppletClass = Class.forName(largeAppletName); / 創(chuàng)建待裝載Applet的實例 Applet largeApplet = (Applet)largeAppletClass.newInstance(); / 設置該Applet的Stub程序 largeApplet.setStub(this); / 取消“請稍等”信息 remove(label); / 設置布局 setLayout (new GridLayout(1, 0); add(largeApplet); / 顯示正式的 Applet l

29、argeApplet.init(); largeApplet.start(); catch (Exception ex) / 顯示錯誤信息 label.setText(不能裝入指定的 Applet); / 刷新屏幕 validate(); public void appletResize(int width, int height) / 把 appletResize調(diào)用從stub程序傳遞到Applet resize(width, height); 編譯后的代碼小于2K,下載速度很快。代碼中有幾個地方值得注意。首先,PreLoader實現(xiàn)了AppletStub接口。一般地,Applet從調(diào)用者判

30、斷自己的codebase。在本例中,我們必須調(diào)用setStub()告訴Applet到哪里提取這個信息。另一個值得注意的地方是, AppletStub接口包含許多和Applet類一樣的方法,但appletResize()方法除外。這里我們把對appletResize()方法的調(diào)用傳遞給了resize()方法。3.3 在畫出圖形之前預先裝入它ImageObserver接口可用來接收圖形裝入的提示信息。ImageObserver接口只有一個方法imageUpdate(),能夠用一次repaint()操作在屏幕上畫出圖形。下面提供了一個例子。public boolean imageUpdate (Im

31、age img, int flags, int x, int y, int w, int h) if (flags & ALLBITS) !=0 repaint(); else if (flags & (ERROR |ABORT ) != 0) error = true; / 文件沒有找到,考慮顯示一個占位符 repaint(); return (flags & (ALLBITS | ERROR| ABORT) = 0; 當圖形信息可用時,imageUpdate()方法被調(diào)用。如果需要進一步更新,該方法返回true;如果所需信息已經(jīng)得到,該方法返回false。3.4 覆蓋update方法upd

32、ate()方法的默認動作是清除屏幕,然后調(diào)用paint()方法。如果使用默認的update()方法,頻繁使用圖形的應用可能出現(xiàn)顯示閃爍現(xiàn)象。要避免在paint()調(diào)用之前的屏幕清除操作,只需按照如下方式覆蓋update()方法:public void update(Graphics g) paint(g); 更理想的方案是:覆蓋update(),只重畫屏幕上發(fā)生變化的區(qū)域,如下所示:public void update(Graphics g) g.clipRect(x, y, w, h); paint(g); 3.5 延遲重畫操作對于圖形用戶界面的應用來說,性能低下的主要原因往往可以歸結為重畫

33、屏幕的效率低下。當用戶改變窗口大小或者滾動一個窗口時,這一點通??梢院苊黠@地觀察到。改變窗口大小或者滾動屏幕之類的操作導致重畫屏幕事件大量地、快速地生成,甚至超過了相關代碼的執(zhí)行速度。對付這個問題最好的辦法是忽略所有“遲到” 的事件。建議在這里引入一個數(shù)毫秒的時差,即如果我們立即接收到了另一個重畫事件,可以停止處理當前事件轉而處理最后一個收到的重畫事件;否則,我們繼續(xù)進行當前的重畫過程。如果事件要啟動一項耗時的工作,分離出一個工作線程是一種較好的處理方式;否則,一些部件可能被“凍結”,因為每次只能處理一個事件。下面提供了一個事件處理的簡單例子,但經(jīng)過擴展后它可以用來控制工作線程。public

34、static void runOnce (String id, final long milliseconds) synchronized(e_queue) / e_queue: 所有事件的集合 if (!e_queue.containsKey(id) e_queue.put(token, new LastOne(); final LastOne lastOne = (LastOne) e_queue.get(token); final long time = System.currentTimeMillis(); / 獲得當前時間 lastOne.time = time; (new Thre

35、ad() public void run () if (milliseconds > 0) try Thread.sleep(milliseconds); / 暫停線程 catch (Exception ex) synchronized(lastOne.running) / 等待上一事件結束 if (lastOne.time != time) / 只處理最后一個事件 return; ).start(); private static Hashtable e_queue = new Hashtable(); private static class LastOne public long

36、time=0; public Object running = new Object(); 3.6 使用雙緩沖區(qū)在屏幕之外的緩沖區(qū)繪圖,完成后立即把整個圖形顯示出來。由于有兩個緩沖區(qū),所以程序可以來回切換。這樣,我們可以用一個低優(yōu)先級的線程負責畫圖,使得程序能夠利用空閑的CPU時間執(zhí)行其他任務。下面的偽代碼片斷示范了這種技術。Graphics myGraphics;Image myOffscreenImage = createImage(size().width, size().height);Graphics offscreenGraphics = myOffscreenImage.getG

37、raphics(); offscreenGraphics.drawImage(img, 50, 50, this);myGraphics.drawImage(myOffscreenImage, 0, 0, this); 3.7 使用BufferedImageJava JDK 1.2使用了一個軟顯示設備,使得文本在不同的平臺上看起來相似。為實現(xiàn)這個功能,Java必須直接處理構成文字的像素。由于這種技術要在內(nèi)存中大量地進行位復制操作,早期的JDK在使用這種技術時性能不佳。為解決這個問題而提出的Java標準實現(xiàn)了一種新的圖形類型,即BufferedImage。BufferedImage子類描述的圖形

38、帶有一個可訪問的圖形數(shù)據(jù)緩沖區(qū)。一個BufferedImage包含一個ColorModel和一組光柵圖形數(shù)據(jù)。這個類一般使用RGB(紅、綠、藍)顏色模型,但也可以處理灰度級圖形。它的構造函數(shù)很簡單,如下所示:public BufferedImage (int width, int height, int imageType) ImageType允許我們指定要緩沖的是什么類型的圖形,比如5-位RGB、8-位RGB、灰度級等。3.8 使用VolatileImage許多硬件平臺和它們的操作系統(tǒng)都提供基本的硬件加速支持。例如,硬件加速一般提供矩形填充功能,和利用CPU完成同一任務相比,硬件加速的效率更

39、高。由于硬件加速分離了一部分工作,允許多個工作流并發(fā)進行,從而緩解了對CPU和系統(tǒng)總線的壓力,使得應用能夠運行得更快。利用VolatileImage可以創(chuàng)建硬件加速的圖形以及管理圖形的內(nèi)容。由于它直接利用低層平臺的能力,性能的改善程度主要取決于系統(tǒng)使用的圖形適配器。VolatileImage的內(nèi)容隨時可能丟失,也即它是“不穩(wěn)定的(volatile)”。因此,在使用圖形之前,最好檢查一下它的內(nèi)容是否丟失。VolatileImage有兩個能夠檢查內(nèi)容是否丟失的方法:public abstract int validate(GraphicsConfiguration gc);public abstr

40、act Boolean contentsLost(); 每次從VolatileImage對象復制內(nèi)容或者寫入VolatileImage時,應該調(diào)用validate()方法。contentsLost()方法告訴我們,自從最后一次validate()調(diào)用之后,圖形的內(nèi)容是否丟失。雖然VolatileImage是一個抽象類,但不要從它這里派生子類。VolatileImage應該通過 Component.createVolatileImage()或者 GraphicsConfiguration.createCompatibleVolatileImage()方法創(chuàng)建。3.9 使用Window Blitt

41、ing進行滾動操作時,所有可見的內(nèi)容一般都要重畫,從而導致大量不必要的重畫工作。許多操作系統(tǒng)的圖形子系統(tǒng),包括WIN32 GDI、MacOS和 X/Windows,都支持Window Blitting技術。Window Blitting技術直接在屏幕緩沖區(qū)中把圖形移到新的位置,只重畫新出現(xiàn)的區(qū)域。要在Swing應用中使用Window Blitting技術,設置方法如下:setScrollMode(int mode); 在大多數(shù)應用中,使用這種技術能夠提高滾動速度。只有在一種情形下,Window Blitting會導致性能降低,即應用四、JavaScript性能優(yōu)化 1.使用局部變量避免使用全局

42、變量比如function test() var s = document.getElementById(aaa); s.innerHTML = document.body.clientHeight; 改成function test() var d = document, s = d.getElementById(aaa); s.innerHTML = d.body.clientHeight;局部變量的好處就是減少了作用域鏈的查找我建議要是有兩次的引用就用局部變量2.避免使用with(這個估計地球人都知道)我理解原因就是with會創(chuàng)建自己的作用域,這樣就加長了原來的作用域鏈,使得在with塊中執(zhí)

43、行的代碼反而變慢了,在書寫上好像省了代碼,其實在訪問上反而變長變繁瑣了,性能下降了。例子 使用with function test() with(document.body) clientHeight = 200px; clientWidth = 200px 其實都可以寫成 function test() var ds = document.body; ds.clientHeight = 200px; ds.clientWidth = 200px 3. 遍歷nodelist的方式 一般的方式都是 var as = document.getElementsByTagName(div); for(

44、var i=0,las.length;il;i+)/只計算一次長度 我的方式一次都不用 for(var i=0,ci;ci=asi+;)當nodeList完結時就為false就結束了 好處,沒計算長度,省了在循環(huán)里賦值,代碼更加少了,i+到了判斷里 (注意:這個方式用在nodelist里可以,如果你用到array里,可會有問題的,數(shù)組里有個0后者null什么的就瞎了) 4.別用那么多個var,一個加逗號就搞定了 var a =1; var b = 1; var c =1; 代碼長,性能差 拆成 var a=1, b=1, c=1; 5.innerHTML是最好的選擇往元素添加元素時,最好用in

45、nerHTML6.ie的removeChild不好用一般咱們刪除一個元素會用 elm.removeChild(subElm)這個在ie下不好用,因為在ie下這個只是把這個元素從dom樹中斷開了,但并沒用真正刪除,它現(xiàn)在變成了孤立的節(jié)點了,要想真正刪除,可以這樣 var ryc = document.createElement(div); div.appendChild(subElm); div.innerHTML = ; div = null;這樣就真的刪除了,除了ie外別的都可以用removeChild達到效果7.為多個同級元素綁定事件時,不用為每個都綁定,為他們的父級綁定就行了比如 sdf

46、sdfsdfsdfsdfsdf 可能你要為每個li添加click 為每個添加那可繁瑣且容易出現(xiàn)溢出(ie) 其實只要為 ul一個添加就行了,因為事件是冒泡向上的 var ul = document.getElementById(a); ul.onclick = function (e) !e&(e=event); var target = e.srcElement|e.target; if(target.tagName=LI) /your code 8.盡量用原生的方法,因為原生的都是用c/c+編譯而成的他們執(zhí)行的要比用js寫的方法快多了9.appendChild用的多時一定要用docuemntfragment比如 for(var i=0;i1000;i+) var o = document.createElement(div); document.body.appendChild(o); 用documentFragment var f = document.createDocumentFragment(); for(var i=0;i=3個了,那用switch吧,好閱讀,性能好11. if=3,別用if了,用3元表達式吧12. if=1,if改& if(a=1)a=2 改 a=1&(a=2);13.計算元素位置,while()offsetParent這個

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論