首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME Timer 與 TimerTask 使用指南:定時任務調度最佳實踐

     編輯:J2ME

前言:輕量級定時器,擺脫 while-sleep 反模式

MIDP 引入 java.util.Timer / TimerTask(J2SE 1.3 同源),以單一後台線程調度所有任務,避免每個動畫/輪詢都開線程導致線程爆炸。本文詳解 API、陷阱、實戰模式。

一、 核心類速覽

類/方法說明
Timer()創建調度器,內部啟動單一守護線程
schedule(TimerTask task, long delay)延遲 delay ms 執行一次
schedule(TimerTask task, long delay, long period)延遲 delay,之後每 period ms 重複(固定延遲)
scheduleAtFixedRate(TimerTask task, long delay, long period)固定頻率:以首次執行時間為基準,追趕延遲
schedule(TimerTask task, Date time)指定絕對時間點執行
TimerTask.cancel()取消自身,從隊列移除
Timer.cancel()終止調度線程,清空隊列,不可重用**

二、 關鍵規則(必讀)

  1. 單線程串行:同一 Timer 同一時刻只能執行一個任務。任務 run() 必須極快返回(< 10ms),否則阻塞後續任務,導致動畫掉幀、定時器漂移。
  2. 異常吞沒:run() 拋出未捕獲異常會導致 Timer 線程死亡,所有已排程任務永不再執行。務必在 run() 內部 try-catch 所有代碼。
  3. 線程安全:Timer 方法線程安全,可多線程並發 schedule。
  4. 一個 MIDlet 通常只需一個 Timer,作為成員變量持有,destroyApp() 時 timer.cancel()。

三、 實戰:星空動畫演示

public class TimerDemo extends MIDlet {
    private Display display;
    private StarField field = new StarField();
    private Timer timer = new Timer();

    protected void startApp() {
        display = Display.getDisplay(this);
        display.setCurrent(field);
        // 100ms 延遲,100ms 週期 → 10 FPS
        timer.schedule(new FieldMover(), 100, 100);
    }

    protected void destroyApp(boolean u) { timer.cancel(); notifyDestroyed(); }
    protected void pauseApp() {}

    // 內部任務類
    class FieldMover extends TimerTask {
        public void run() {
            try { field.scroll(); } catch (Exception e) { e.printStackTrace(); }
        }
    }

    // 低級 UI 繪製
    class StarField extends Canvas {
        int h, w; int[] stars; Random r = new Random(); boolean painting;

        public StarField() {
            h = getHeight(); w = getWidth();
            stars = new int[h];
            for (int i=0; i0; i--) stars[i] = stars[i-1];
            stars[0] = (r.nextInt() % (3*w)) / 2;
            if (stars[0] >= w) stars[0] = -1;
            repaint(0, 0, w, h); // 部分重繪
        }

        protected void paint(Graphics g) {
            painting = true;
            g.setColor(0); g.fillRect(0,0,w,h);
            g.setColor(0xFFFFFF);
            for (int y=0; y

四、 進階模式:動態增減任務、固定頻率 vs 固定延遲

  • 動畫/遊戲幀:用 scheduleAtFixedRate,保證長期平均幀率精準(如 20 FPS = 50ms),即使單幀偶爾超時也會追趕。
  • 輪詢/心跳/同步:用 schedule(task, delay, period)(固定延遲),允許任務執行時間抖動,不追趕,避免擠佔 CPU。
  • 一次性延遲執行:schedule(task, 5000) 替代 Thread.sleep(5000),不阻塞業務線程。
  • 運行時增減:timer.schedule(new OneShotTask(), 0) 立即插入;任務內 this.cancel() 自銷毀。

五、 避坑清單

現象原因修正
定時器停止不執行run() 拋出異常導致 Timer 線程死掉run() 內部包裹 try-catch(Exception e){log}
動畫卡頓、幀率不穩run() 耗時 > period將耗時運算移至獨立線程,run() 只做狀態更新+repaint
銷毀後仍收到回調Timer 未 cancel,任務仍在隊列destroyApp() 必調 timer.cancel()
多 Timer 導致內存/線程洩漏到處 new Timer()全局單例 Timer,模塊共享

六、 總結

Timer/TimerTask 是 J2ME 定時調度的標準解法:單線程、串行、輕量。核心紀律是「任務極快、異常全捕獲、統一生命週期管理」。掌握固定頻率與固定延遲的語義區別,能讓動畫流暢、輪詢穩健、資源釋放乾淨。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved