將執行緒邏輯、UI 元件與狀態封裝於單一類別,支援建立任意數量獨立運作的執行緒實例。本範例展示每個計數器擁有專屬按鈕、顯示欄位與執行緒控制。
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
class Ticker extends Thread {
private Button toggleBtn = new Button("Toggle");
private TextField display = new TextField(10);
private int count = 0;
private boolean running = true;
public Ticker(Container parent) {
// 事件監聽器
toggleBtn.addActionListener(e -> running = !running);
// 佈局:面板包含顯示欄與按鈕
Panel p = new Panel();
p.add(display);
p.add(toggleBtn);
parent.add(p); // 加入父容器
}
@Override
public void run() {
while (true) {
if (running) display.setText(String.valueOf(count++));
try { sleep(100); } catch (InterruptedException ignored) {}
}
}
}
public class Counter4 extends Applet {
private Button startBtn = new Button("Start");
private boolean started = false;
private Ticker[] tickers;
private boolean isApplet = true;
private int size;
public void init() {
// 從網頁參數或命令列取得計數器數量
if (isApplet) size = Integer.parseInt(getParameter("size"));
tickers = new Ticker[size];
for (int i = 0; i < size; i++) tickers[i] = new Ticker(this);
startBtn.addActionListener(e -> {
if (!started) {
started = true;
for (Ticker t : tickers) t.start();
}
});
add(startBtn);
}
// 應用程式進入點
public static void main(String[] args) {
Counter4 applet = new Counter4();
applet.isApplet = false;
applet.size = (args.length == 0) ? 5 : Integer.parseInt(args[0]);
Frame frame = new Frame("Counter4");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
frame.add(applet, BorderLayout.CENTER);
frame.setSize(200, applet.size * 50);
applet.init();
applet.start();
frame.setVisible(true);
}
}
<applet code=Counter4 width=600 height=600>
<param name=size value="20">
</applet>
| 特性 | 實作方式 | 優勢 |
|---|---|---|
| 狀態封裝 | count、running、UI 元件皆為 private | 內部實作可任意變更不影響外部 |
| UI 自包含 | 建構子接收 Container,自行組裝加入 | 使用端無需知道內部元件細節 |
| 動態數量 | 陣列長度由參數決定 | 部署時靈活調整,無需重編譯 |
| 雙模式執行 | isApplet 旗標切換 Applet/Application | 開發測試與部署無縫切換 |
getParameter() 必須在 init() 中呼叫,Applet 框架尚未初始化參數時無法取得。sleep(100) 釋放 CPU,避免忙碌等待。移除會導致切換按鈕無回應(執行緒佔滿 CPU)。start() 啟動執行緒,run() 為執行本體,**切勿直接呼叫 run()**。JButton, JTextField) 並透過 SwingUtilities.invokeLater 更新 UI。interrupt() 協作式終止。ExecutorService 管理執行緒池,替代手動陣列。