一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java性能優(yōu)化技巧集錦[續(xù)]

 鳳舞天煌 2007-11-12
三、GUI篇

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

  3.1 用JAR壓縮類文件

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

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

  3.2 提示Applet裝入進程

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

  下面我們來看看一種具體的實現(xiàn)方法。首先創(chuàng)建一個很小的Applet,該Applet負(fù)責(zé)在后臺下載正式的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);

   // 創(chuàng)建待裝載Applet的實例

   Applet largeApplet = (Applet)largeAppletClass.newInstance();

   // 設(shè)置該Applet的Stub程序

   largeApplet.setStub(this);

   // 取消“請稍等”信息

   remove(label);

   // 設(shè)置布局

   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調(diào)用從stub程序傳遞到Applet

  resize(width, height);

   }

  }




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

  3.3 在畫出圖形之前預(yù)先裝入它

  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;

  }




  當(dāng)圖形信息可用時,imageUpdate()方法被調(diào)用。如果需要進一步更新,該方法返回true;如果所需信息已經(jīng)得到,該方法返回false。

  3.4 覆蓋update方法

  update()方法的默認(rèn)動作是清除屏幕,然后調(diào)用paint()方法。如果使用默認(rèn)的update()方法,頻繁使用圖形的應(yīng)用可能出現(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 延遲重畫操作

  對于圖形用戶界面的應(yīng)用來說,性能低下的主要原因往往可以歸結(jié)為重畫屏幕的效率低下。當(dāng)用戶改變窗口大小或者滾動一個窗口時,這一點通??梢院苊黠@地觀察到。改變窗口大小或者滾動屏幕之類的操作導(dǎo)致重畫屏幕事件大量地、快速地生成,甚至超過了相關(guān)代碼的執(zhí)行速度。對付這個問題最好的辦法是忽略所有“遲到”的事件。

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

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

  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();

   // 獲得當(dāng)前時間

   lastOne.time = time;

   (new Thread()

   {

  public void run()

  {

   if (milliseconds > 0)

   {

    try

    {

     Thread.sleep(milliseconds);

    }

    // 暫停線程

    atch (Exception ex) {}

   }

   synchronized(lastOne.running)

   {

    // 等待上一事件結(jié)束

    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 使用雙緩沖區(qū)

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

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使用了一個軟顯示設(shè)備,使得文本在不同的平臺上看起來相似。為實現(xiàn)這個功能,Java必須直接處理構(gòu)成文字的像素。由于這種技術(shù)要在內(nèi)存中大量地進行位復(fù)制操作,早期的JDK在使用這種技術(shù)時性能不佳。為解決這個問題而提出的Java標(biāo)準(zhǔn)實現(xiàn)了一種新的圖形類型,即BufferedImage。

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

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

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

  3.8 使用VolatileImage

  許多硬件平臺和它們的操作系統(tǒng)都提供基本的硬件加速支持。例如,硬件加速一般提供矩形填充功能,和利用CPU完成同一任務(wù)相比,硬件加速的效率更高。由于硬件加速分離了一部分工作,允許多個工作流并發(fā)進行,從而緩解了對CPU和系統(tǒng)總線的壓力,使得應(yī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 abstract Boolean contentsLost();

  每次從VolatileImage對象復(fù)制內(nèi)容或者寫入VolatileImage時,應(yīng)該調(diào)用validate()方法。contentsLost()方法告訴我們,自從最后一次validate()調(diào)用之后,圖形的內(nèi)容是否丟失。

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

  3.9 使用Window Blitting

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

  setScrollMode(int mode);

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

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    一区二区三区四区亚洲另类| 97人妻精品免费一区二区| 九九热国产这里只有精品| 91偷拍视频久久精品| 国产精品亚洲一级av第二区| 亚洲免费视频中文字幕在线观看| 91偷拍视频久久精品| 视频一区二区三区自拍偷| 激情丁香激情五月婷婷| 国产精品推荐在线一区| 亚洲熟女乱色一区二区三区| 麻豆国产精品一区二区三区| 日本不卡片一区二区三区| 中文字幕精品少妇人妻| 亚洲一区二区三区av高清| 欧美成人免费夜夜黄啪啪| 成人亚洲国产精品一区不卡| 亚洲国产av国产av| 日韩日韩日韩日韩在线| 国产亚洲精品一二三区| 日韩成人h视频在线观看| 国产午夜福利不卡片在线观看| 国产精品久久女同磨豆腐| 国产一区欧美一区二区| 亚洲乱妇熟女爽的高潮片| 亚洲视频一区二区久久久| 国语久精品在视频在线观看| 久久精品中文字幕人妻中文| 亚洲精品日韩欧美精品| 欧美国产极品一区二区| 国产精品乱子伦一区二区三区| 亚洲精品av少妇在线观看| 熟女中文字幕一区二区三区| 日韩一区欧美二区国产| 91精品国产av一区二区| 欧美一区日韩二区亚洲三区| 老外那个很粗大做起来很爽| 中文字幕乱子论一区二区三区| 国产免费观看一区二区| 五月婷日韩中文字幕四虎| 成人免费观看视频免费|