六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

Java優化性能技巧集錦(2)

[摘要]三、GUI篇 這一部分介紹的內容適合于圖形用戶界面的應用(Applet和普通應用),要用到AWT或Swing。 3.1 用JAR壓縮類文件 Java檔案文件(JAR文件)是根據JavaBean標準壓縮的文件,是發布JavaBean組件的主要方式和推薦方式。JAR檔案有助于減少文件體積,縮短下載時間...
三、GUI篇

這一部分介紹的內容適合于圖形用戶界面的應用(Applet和普通應用),要用到AWT或Swing。

3.1 用JAR壓縮類文件

Java檔案文件(JAR文件)是根據JavaBean標準壓縮的文件,是發布JavaBean組件的主要方式和推薦方式。JAR檔案有助于減少文件體積,縮短下載時間。例如,它有助于Applet提高啟動速度。一個JAR文件可以包含一個或者多個相關的Bean以及支持文件,比如圖形、聲音、HTML和其他資源。

要在HTML/JSP文件中指定JAR文件,只需在Applet標記中加入ARCHIVE = "name.jar"聲明。

請參見《使用檔案文件提高 applet 的加載速度》。

3.2 提示Applet裝入進程

你是否看到過使用Applet的網站,注意到在應該運行Applet的地方出現了一個占位符?當Applet的下載時間較長時,會發生什么事情?最大的可能就是用戶掉頭離去。在這種情況下,顯示一個Applet正在下載的信息無疑有助于鼓勵用戶繼續等待。

下面我們來看看一種具體的實現方法。首先創建一個很小的Applet,該Applet負責在后臺下載正式的Applet:


import java.applet.Applet;
import java.applet.AppletStub;
import java.awt.Label;
import java.awt.Graphics;
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(){
try {
 // 獲得待裝載Applet的類
 Class largeAppletClass = Class.forName(largeAppletName);
 // 創建待裝載Applet的實例
Applet largeApplet = (Applet)largeAppletClass.newInstance();
 // 設置該Applet的Stub程序
 largeApplet.setStub(this);
 // 取消“請稍等”信息
remove(label);
// 設置布局
setLayout(new GridLayout(1, 0));
add(largeApplet);
// 顯示正式的Applet
largeApplet.init();
largeApplet.start();
 }
 catch (Exception ex) {
// 顯示錯誤信息
label.setText("不能裝入指定的Applet");
 }
 // 刷新屏幕
 validate();
}
public void appletResize(int width, int height) {
// 把appletResize調用從stub程序傳遞到Applet
 resize(width, height);
}
}



編譯后的代碼小于2K,下載速度很快。代碼中有幾個地方值得注意。首先,PreLoader實現了AppletStub接口。一般地,Applet從調用者判斷自己的codebase。在本例中,我們必須調用setStub()告訴Applet到哪里提取這個信息。另一個值得注意的地方是,AppletStub接口包含許多和Applet類一樣的方法,但appletResize()方法除外。這里我們把對appletResize()方法的調用傳遞給了resize()方法。

3.3 在畫出圖形之前預先裝入它

ImageObserver接口可用來接收圖形裝入的提示信息。ImageObserver接口只有一個方法imageUpdate(),能夠用一次repaint()操作在屏幕上畫出圖形。下面提供了一個例子。


public boolean imageUpdate(Image 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()方法被調用。如果需要進一步更新,該方法返回true;如果所需信息已經得到,該方法返回false。

3.4 覆蓋update方法

update()方法的默認動作是清除屏幕,然后調用paint()方法。如果使用默認的update()方法,頻繁使用圖形的應用可能出現顯示閃爍現象。要避免在paint()調用之前的屏幕清除操作,只需按照如下方式覆蓋update()方法:


public void update(Graphics g) {
paint(g);
}



更理想的方案是:覆蓋update(),只重畫屏幕上發生變化的區域,如下所示:


public void update(Graphics g) {
g.clipRect(x, y, w, h);
paint(g);
}



3.5 延遲重畫操作

對于圖形用戶界面的應用來說,性能低下的主要原因往往可以歸結為重畫屏幕的效率低下。當用戶改變窗口大小或者滾動一個窗口時,這一點通常可以很明顯地觀察到。改變窗口大小或者滾動屏幕之類的操作導致重畫屏幕事件大量地、快速地生成,甚至超過了相關代碼的執行速度。對付這個問題最好的辦法是忽略所有“遲到”的事件。

建議在這里引入一個數毫秒的時差,即如果我們立即接收到了另一個重畫事件,可以停止處理當前事件轉而處理最后一個收到的重畫事件;否則,我們繼續進行當前的重畫過程。

如果事件要啟動一項耗時的工作,分離出一個工作線程是一種較好的處理方式;否則,一些部件可能被“凍結”,因為每次只能處理一個事件。下面提供了一個事件處理的簡單例子,但經過擴展后它可以用來控制工作線程。


public 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 Thread() {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 time=0;
 public Object running = new Object();
}



3.6 使用雙緩沖區

在屏幕之外的緩沖區繪圖,完成后立即把整個圖形顯示出來。由于有兩個緩沖區,所以程序可以來回切換。這樣,我們可以用一個低優先級的線程負責畫圖,使得程序能夠利用空閑的CPU時間執行其他任務。下面的偽代碼片斷示范了這種技術。


Graphics myGraphics;
Image myOffscreenImage = createImage(size().width, size().height);
Graphics offscreenGraphics = myOffscreenImage.getGraphics();
offscreenGraphics.drawImage(img, 50, 50, this);
myGraphics.drawImage(myOffscreenImage, 0, 0, this);



3.7 使用BufferedImage

Java JDK 1.2使用了一個軟顯示設備,使得文本在不同的平臺上看起來相似。為實現這個功能,Java必須直接處理構成文字的像素。由于這種技術要在內存中大量地進行位復制操作,早期的JDK在使用這種技術時性能不佳。為解決這個問題而提出的Java標準實現了一種新的圖形類型,即BufferedImage。

BufferedImage子類描述的圖形帶有一個可訪問的圖形數據緩沖區。一個BufferedImage包含一個ColorModel和一組光柵圖形數據。這個類一般使用RGB(紅、綠、藍)顏色模型,但也可以處理灰度級圖形。它的構造函數很簡單,如下所示:


public BufferedImage (int width, int height, int imageType)



ImageType允許我們指定要緩沖的是什么類型的圖形,比如5-位RGB、8-位RGB、灰度級等。

3.8 使用VolatileImage

許多硬件平臺和它們的操作系統都提供基本的硬件加速支持。例如,硬件加速一般提供矩形填充功能,和利用CPU完成同一任務相比,硬件加速的效率更高。由于硬件加速分離了一部分工作,允許多個工作流并發進行,從而緩解了對CPU和系統總線的壓力,使得應用能夠運行得更快。利用VolatileImage可以創建硬件加速的圖形以及管理圖形的內容。由于它直接利用低層平臺的能力,性能的改善程度主要取決于系統使用的圖形適配器。VolatileImage的內容隨時可能丟失,也即它是“不穩定的(volatile)”。因此,在使用圖形之前,最好檢查一下它的內容是否丟失。VolatileImage有兩個能夠檢查內容是否丟失的方法:


public abstract int validate(GraphicsConfiguration gc);
public abstract Boolean contentsLost();



每次從VolatileImage對象復制內容或者寫入VolatileImage時,應該調用validate()方法。contentsLost()方法告訴我們,自從最后一次validate()調用之后,圖形的內容是否丟失。

雖然VolatileImage是一個抽象類,但不要從它這里派生子類。VolatileImage應該通過Component.createVolatileImage()或者GraphicsConfiguration.createCompatibleVolatileImage()方法創建。

3.9 使用Window Blitting

進行滾動操作時,所有可見的內容一般都要重畫,從而導致大量不必要的重畫工作。許多操作系統的圖形子系統,包括WIN32 GDI、MacOS和X/Windows,都支持Window Blitting技術。Window Blitting技術直接在屏幕緩沖區中把圖形移到新的位置,只重畫新出現的區域。要在Swing應用中使用Window Blitting技術,設置方法如下:


setScrollMode(int mode);



在大多數應用中,使用這種技術能夠提高滾動速度。只有在一種情形下,Window Blitting會導致性能降低,即應用在后臺進行滾動操作。如果是用戶在滾動一個應用,那么它總是在前臺,無需擔心任何負面影響。

四、補充資料




主站蜘蛛池模板: 永久免费毛片 | 午夜h视频| 四虎影永久在线观看网址 | 一区二区精品 | 亚洲国产成人久久综合碰 | 午夜网站在线观看免费网址免费 | 亚州免费视频 | 欧美一级高清片在线 | 在线午夜 | 亚洲wuma| 香蕉三级 | 亚洲视频在线观看网站 | 青青青国产色视频在线观看 | 中文字幕乱视频 | 欧美一级视频高清片 | 欧美一级一级做性视频 | 四虎精品视频 | 日本高清免费中文在线看 | 欧美一级黄色片子 | 日韩欧美黄色片 | 欧日韩美香蕉在线观看 | 色姣姣狠狠撩综合网 | 日本大蕉香蕉大视频在线观看 | 婷婷激情小说网 | 欧美欲乱妇135 | 午夜精品视频5000 | 亚洲第一成年网 | 亚洲综合一 | 五月婷婷婷 | 深夜爽爽福利gif在线观看 | 日韩在线操| 日韩欧美国产另类 | 日本一区二区影院 | 无人码一区二区三区视频 | 五月激情站 | 日本视频在线观看播放免费 | 四虎最新网站 | 亚洲成人黄色片 | 特一级黄色片 | 日韩高清的天堂在线观看免费 | 欧美特级淫片 |