views:

166

answers:

1

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();
}
+2  A: 

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.
Catchwa
Great advice for the options! Though to clarify: the timer is terminated even though I'm calling cancel() on the TimerTask and not the static Timer itself?
vazor
Yeah, I mis-read that. You should be able to cancel the TimerTask without any problems. If you're 100% sure that your calls are only to TimerTask.cancel() and not Timer.cancel() then have a look here: http://www.coderanch.com/t/452066/java/java/Exception-timer-IllegalStateException
Catchwa