J2ME (Java ME) 是 2000 年代功能機、早期智慧型手機的主流開發平台。裝置記憶體只有 1-2 MB、CPU 極慢、網路延遲高且不穩。若在主執行緒 (MIDlet 主事件迴路) 直接呼叫 Connector.open() 進行 HTTP 連線,畫面會凍結數秒甚至分鐘,使用者無法操作、甚至被系統判定為「當機」強制關閉。因此多執行緒不是優化,是生存門檻。
javax.microedition.io 定義了分層介面:
Connection → StreamConnection → ContentConnection → HttpConnectionDatagramConnection (UDP)SocketConnection (TCP)MIDP 1.0 強制實作 HTTP;MIDP 2.0 新增 HTTPS。所有 I/O 皆為阻塞式,必須另開執行緒。
public void commandAction(Command c, Displayable d) {
if (c == sendCmd) new Thread(new NetWorker()).start();
}
class NetWorker implements Runnable {
public void run() {
HttpConnection hc = null;
try {
hc = (HttpConnection) Connector.open(url);
int rc = hc.getResponseCode();
if (rc == HttpConnection.HTTP_OK) {
// 讀取資料...
display.setCurrent(resultForm); // 切換 UI 必須在事件執行緒
}
} catch (IOException e) { /* 錯誤處理 */ }
finally { if (hc != null) try { hc.close(); } catch (IOException ignore) {} }
}
}
缺點:使用者連點兩次按鈕會產生兩條執行緒,資源浪費且可能競爭。
class NetDispatcher implements Runnable {
private boolean busy = false;
private String pendingUrl;
private final Object lock = new Object();
public void dispatch(String url) {
synchronized (lock) {
pendingUrl = url;
if (!busy) { busy = true; new Thread(this).start(); }
else lock.notify(); // 喚醒既有執行緒
}
}
public void run() {
while (true) {
String url;
synchronized (lock) {
while (pendingUrl == null) {
try { lock.wait(); } catch (InterruptedException ignore) {}
}
url = pendingUrl; pendingUrl = null;
}
doRequest(url); // 實際連線邏輯
synchronized (lock) { if (pendingUrl == null) { busy = false; break; } }
}
}
}
優點:同一時間只有一條網路執行緒,請求自動排隊,無競爭、無洩漏。
class HeartbeatTask extends TimerTask {
private final Timer timer = new Timer();
public void start() { timer.schedule(this, 0, 30_000); } // 30 秒一次
public void run() { sendHeartbeat(); }
public void stop() { timer.cancel(); }
}
注意:Timer 內部只有一條執行緒,任務若阻塞會延遲後續任務;網路請求建議仍用專屬執行緒池。
hc.setRequestProperty("Connection", "close"); 避免 Keep-Alive 卡死。InputStream/OutputStream/HttpConnection 全部關閉。Display.callSerially(Runnable),Android 用 runOnUiThread/Handler,Swing 用 SwingUtilities.invokeLater。cancel() 讓使用者可中止長連線,釋放資源。雖然 J2ME 已成歷史,但「阻塞 I/O 必須離開主執行緒、生產者/消費者模式解耦請求與執行、生命週期管理防洩漏」這三大原則,放在現代 Android、Java SE、嵌入式 Java 開發依然完全通用。理解當年的約束,更能體會今天 CompletableFuture、RxJava、Coroutines 設計的精妙。