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

发布于 2024-09-13 05:56:05 字数 789 浏览 4 评论 0原文

所以我正在运行一个 Java 服务器,并且在一个类中我有一个静态计时器。然后我有另一个类,它在程序的整个生命周期中有许多实例被创建和销毁,每个实例都有自己的 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();
}

So I'm running a Java server and in one class I have a static Timer. Then I have another class which has many instances being created and destroyed throughout the life of the program, each with their own TimerTask (using the static Timer). When an instance is destroyed, it calls cancel() on the TimerTask.

The problem is, I'm not sure if this is good design, and also I get errors sometimes when the instance is creating and scheduling its TimerTask:

     java.lang.IllegalStateException: Timer already cancelled.

Here is some code to show what I mean.

/**
 * 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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

回眸一笑 2024-09-20 05:56:05

该错误是因为当您调用 cancel() 时,Timer 已“死亡”,您无法对其执行任何其他操作。

来自 API

一旦计时器终止,其执行线程就会正常终止,并且不能在其上调度更多任务。

您有几个选择:

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

The error is because when you call cancel() the Timer is 'dead' and you can't do anything else with it.

From the API:

Once a timer has been terminated, its execution thread terminates gracefully, and no more tasks may be scheduled on it.

You have a few options:

  1. Get rid of the static Timer and instead hold a separate instance of Timer within each object. That way when the object is destroyed, you can also destroy the Timer without affecting the other TimerTasks. This will mean one timer thread per object.
  2. Keep the static Timer but also hold in memory (e.g. in an ArrayList<TimerTask>) a list of all the tasks within it. Then when an object is destroyed, you re-create the static Timer object using the in-memory list of tasks (minus the one corresponding to the object you destoryed). The consequence of this is that the execution of the remaining TimerTasks may need some finessing (particularly if you don't want them all to 'bunch up').
  3. Extend or write your own Timer-like class to allow for the removal of TimerTasks. (Someone may have already done this, I don't know)
  4. Use a ScheduledThreadPoolExecutor which allows you to remove tasks.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文