Timer:單一後台執行緒,循序執行所有排程任務,線程安全。TimerTask:抽象類,繼承並實作 run() 定義任務邏輯。| 方法 | 說明 |
|---|---|
schedule(task, time) | 指定時間執行一次 |
schedule(task, delay) | 延遲指定毫秒執行一次 |
schedule(task, delay, period) | 延遲後每隔 period 執行(固定延遲) |
scheduleAtFixedRate(task, delay, period) | 延遲後每隔 period 執行(固定頻率) |
差異:schedule 以「上次實際執行時間 + period」為下次計劃時間(保間隔);scheduleAtFixedRate 以「首次計劃時間 + n*period」為計劃時間(保頻率),任務超時會並發執行追趕進度。
new Timer().schedule(new TimerTask() {
public void run() { System.out.println("Time's up!"); }
}, 3000);
Calendar cal = Calendar.getInstance();
cal.set(2025, Calendar.JANUARY, 1, 0, 0, 0);
new Timer().schedule(new TimerTask() { ... }, cal.getTime());
new Timer().schedule(new TimerTask() {
public void run() { System.out.println("Tick: " + new Date()); }
}, 1000, 2000); // 1秒後開始,每2秒一次
TimerTask 拋出未檢查異常會終結 Timer 執行緒,導致後續任務永不執行。基於執行緒池、支援並發、異常隔離、基於絕對時間(NanoTime),JDK 5+ 推薦。
ScheduledExecutorService exec = Executors.newScheduledThreadPool(2);
// 固定延遲
exec.scheduleWithFixedDelay(() -> {
System.out.println("Task A");
try { Thread.sleep(4000); } catch (InterruptedException e) {}
}, 1, 2, TimeUnit.SECONDS);
// 固定頻率
exec.scheduleAtFixedRate(() -> System.out.println("Task B"), 2, 1, TimeUnit.SECONDS);
輸出顯示 Task B 不受 Task A 阻塞影響,準時執行。
// Timer: 任務拋出 RuntimeException -> 整個 Timer 死掉
// ScheduledThreadPoolExecutor: 單任務異常不影響其他任務
exec.schedule(() -> { throw new RuntimeException(); }, 1, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(() -> System.out.println("Still alive"), 2, 1, TimeUnit.SECONDS);
用 javax.swing.Timer(事件派發執行緒安全)驅動重繪,JSpinner 調整延遲控制速度。
public class BallsCanvas extends JPanel implements ActionListener {
private final Ball[] balls;
private final Timer timer;
public BallsCanvas(Color[] colors, int delay) {
balls = new Ball[colors.length];
for (int i = 0; i < colors.length; i++)
balls[i] = new Ball(40 + i*40, 40 + i*40, colors[i]);
timer = new Timer(delay, this);
timer.start();
}
public void setDelay(int d) { timer.setDelay(d); }
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball b : balls) {
g.setColor(b.color);
b.move(getWidth(), getHeight());
g.fillOval(b.x, b.y, 20, 20);
}
}
@Override public void actionPerformed(ActionEvent e) { repaint(); }
static class Ball {
int x, y; Color color; boolean left, up;
Ball(int x, int y, Color c) { this.x=x; this.y=y; this.color=c; }
void move(int maxW, int maxH) {
x += left ? -10 : 10; if (x<0 || x>=maxW) left = !left;
y += up ? -10 : 10; if (y<0 || y>=maxH) up = !up;
}
}
}
Timer 夠用。ScheduledThreadPoolExecutor。javax.swing.Timer 保證 EDT 安全。