Java 程式主要分為兩類:Applet(小程式)與 Application(應用程式)。兩者差異顯著:Applet 嵌入網頁中,隨頁面下載並在瀏覽器的 JVM 中執行,受安全機制限制(如無法存取本地檔案);Application 則獨立於瀏覽器運行,擁有完整系統權限。程式結構上最大的不同在於——Applet 沒有 main() 方法,而 Application 必須有。
每個 Applet 皆繼承自 java.applet.Applet 類別。開發者透過覆寫五大核心方法來掌控生命週期:
init():首次載入頁面時調用,負責初始化start():Applet 開始/恢復運行時調用paint(Graphics g):繪製畫面內容stop():用戶離開頁面時調用,暫停執行destroy():瀏覽器關閉時調用,釋放資源生命週期與網頁綁定:只要瀏覽器不關閉,重新載入頁面只會觸發 start() 與 paint(),不會重複 init()。
實用的 Applet(動畫、即時資料抓取)通常包含無限迴圈的邏輯主體。若直接放在 init() 或 paint() 中,會佔用單一事件執行緒,導致瀏覽器無法回應使用者操作(選單失效、頁面無法切換)。
解決之道:引入執行緒,將主邏輯移至 run() 方法。在 start() 啟動執行緒,stop() 終止它,確保離開頁面時不佔用 CPU。
為了複用,我們可建立一個支援執行緒的基類 MultiThreadApplet:
import java.applet.*;
import java.awt.*;
class MultiThreadApplet extends Applet implements Runnable {
Thread thisThread;
public void start() {
if (thisThread == null) {
thisThread = new Thread(this);
thisThread.start();
}
}
public void stop() {
if (thisThread != null) {
thisThread.stop(); // 注意:stop() 已棄用,現代建議用 interrupt() + 旗標
thisThread = null;
}
}
public void run() { } // 留給子類實作
}
使用範例——計數器動畫:
import java.awt.*;
public class Counter extends MultiThreadApplet {
int counter = 0;
public void run() {
while (true) {
counter++;
repaint(); // 觸發 paint()
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
}
}
public void paint(Graphics g) {
g.drawString(String.valueOf(counter), 10, 10);
}
}
執行緒控制細節被封裝在基類中,子類專注於業務邏輯。
動畫本質是連續靜態圖形的快速切換。若直接在螢幕上「清除→重繪背景→繪製新位置」,畫面會因刷新時機不一致而閃爛。
createImage(width, height) 建立離屏影像緩衝區Graphics 物件,對它進行「清除、畫背景、畫物件」drawImage(offscreenImage, 0, 0, this) 輸出到螢幕範例——彈跳小球(無閃爛):
import java.awt.*;
public class Ball extends MultiThreadApplet {
Image offscreen, ballImg;
Graphics offG, ballG;
public void run() {
if (ballImg == null) {
offscreen = createImage(bounds().width, bounds().height);
ballImg = createImage(70, 70);
offG = offscreen.getGraphics();
ballG = ballImg.getGraphics();
ballG.setColor(Color.gray);
ballG.fillOval(0, 0, 70, 70);
}
for (int x = 0; x < 400; x++) {
double angle = x / 20.0;
int y = (int) (Math.abs(Math.sin(angle)) * 80);
offG.clearRect(0, 0, bounds().width, bounds().height);
drawBackground(offG);
offG.drawImage(ballImg, x, 80 + y, this);
getGraphics().drawImage(offscreen, 0, 0, this);
try { Thread.sleep(25); } catch (Exception ignored) {}
}
}
private void drawBackground(Graphics g) {
for (int i = 0; i < 40; i++) {
g.drawLine(0, i * 10, 400, i * 10);
}
}
}
執行結果:動畫絲滑流暢,零閃爛。
功能豐富的 Applet 體積較大,下載耗時長。優化三維度:
網路傳輸以封包為單位(通常 256 位元組倍數),最後一個封包若極小,等待重組會造成秒級延遲。保持 .class 檔盡量小:
javac -O)下載 20 個小類別比下載 1 個等量大類別慢(每次連線握手都有開銷)。設計時在「結構清晰」與「精簡無冗餘」間取得平衡。
使用者討厭等待。若初始化耗時,可啟動輔助執行緒先與用戶互動(歡迎語、詢問姓名、顯示進度條),主執行緒在後台完成初始化。「興奮時時間過得快」——善用心理學改善體感效能。
本文系統整理了 Applet 開發的核心技巧,從生命週期理解到多線程架構、動畫渲染優化、網路載入加速,為構建高品質 Java 客戶端應用提供實戰指引。