Java静态定时器可以处理多个调用cancel()的TimerTasks吗?

时间:2010-08-10 00:43:25

标签: java multithreading timer task

所以我正在运行一个Java服务器,在一个类中我有一个静态Timer。然后我有另一个类,它在程序的整个生命周期中创建和销毁了许多实例,每个实例都有自己的TimerTask(使用静态Timer)。当一个实例被销毁时,它会在TimerTask上调用cancel()。

问题是,我不确定这是不是很好的设计,而且当实例创建和调度TimerTask时我也会遇到错误:

     java.lang.IllegalStateException: Timer already cancelled.

这是一些显示我的意思的代码。

/**
 * Starts scheduled tasks using TimerTask
 */
private void initTasks()
{
    // room heartbeat thread:  start immediately, run once every second
    roomHeartbeatTask = new RoomHeartbeatTask(this);
    RoomListExtension.roomHeartbeat.schedule(roomHeartbeatTask, 0, 1000);
    // add additional tasks here
}

/**
 * Cancels all tasks that have been started by this extension
 */
private void cancelTasks()
{
    roomHeartbeatTask.cancel();
}

1 个答案:

答案 0 :(得分:5)

错误是因为当您致电cancel()时,Timer已“死亡”且您无法对其进行任何其他操作。

来自API

  

一旦计时器终止,其执行线程将正常终止,并且不再安排任何任务。

您有几个选择:

  1. 摆脱静态Timer,而在每个对象中保留一个单独的Timer实例。这样,当对象被销毁时,您也可以销毁Timer而不影响其他TimerTask。这意味着每个对象有一个计时器线程。
  2. 保留静态Timer,但也要在内存中保存(例如在ArrayList<TimerTask>中)其中所有任务的列表。然后,当一个对象被销毁时,使用内存中的任务列表(减去与您要销毁的对象相对应的一个)重新创建静态Timer对象。这样做的结果是剩下的TimerTask的执行可能需要一些精力(特别是如果你不希望它们全部'聚集')。
  3. 扩展或编写您自己的Timer类,以便删除TimerTask。 (有人可能已经这样做了,我不知道)
  4. 使用ScheduledThreadPoolExecutor可以删除任务。