Может ли статический таймер Java обрабатывать несколько задач TimerTask, вызывающих отмену ()?

Итак, я запускаю сервер Java, и в одном классе у меня есть статический таймер. Затем у меня есть еще один класс, в котором много экземпляров создается и уничтожается на протяжении всей жизни программы, каждый со своим собственным TimerTask (с использованием статического таймера). Когда экземпляр уничтожается, он вызывает метод cancel() в TimerTask.

Проблема в том, что я не уверен, что это хороший дизайн, а также я иногда получаю ошибки, когда экземпляр создает и планирует свою 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();
}

person vazor    schedule 10.08.2010    source источник


Ответы (1)


Ошибка в том, что когда вы вызываете cancel(), Timer "мертв", и вы не можете ничего с ним сделать.

Из API :

Как только таймер был остановлен, его поток выполнения корректно завершается, и для него больше нельзя планировать задачи.

У вас есть несколько вариантов:

  1. Избавьтесь от статического Timer и вместо этого держите отдельный экземпляр Timer в каждом объекте. Таким образом, когда объект уничтожается, вы также можете уничтожить Timer, не затрагивая другие TimerTask. Это будет означать один поток таймера на объект.
  2. Сохраняйте статический Timer, но также храните в памяти (например, в ArrayList<TimerTask>) список всех задач внутри него. Затем, когда объект уничтожается, вы воссоздаете статический объект Timer, используя список задач в памяти (минус тот, который соответствует объекту, который вы уничтожили). Следствием этого является то, что выполнение оставшихся TimerTasks может потребовать некоторой доработки (особенно если вы не хотите, чтобы они все "сгруппировались").
  3. Расширьте или напишите свой собственный класс, подобный Timer, чтобы разрешить удаление TimerTask. (может кто-то это уже делал, я не знаю)
  4. Используйте ScheduledThreadPoolExecutor, который позволяет удалить задачи.
person Catchwa    schedule 10.08.2010
comment
Отличный совет по вариантам! Хотя, чтобы уточнить: таймер завершается, даже если я вызываю отмену () для TimerTask, а не для самого статического таймера? - person vazor; 10.08.2010
comment
Да, я неправильно прочитал это. Вы должны быть в состоянии отменить TimerTask без каких-либо проблем. Если вы на 100 % уверены, что ваши вызовы относятся только к TimerTask.cancel(), а не к Timer.cancel(), посмотрите здесь: coderanch.com/t/452066/java/java/ - person Catchwa; 11.08.2010
comment
ScheduledThreadPoolExecutor также решил мою проблему, спасибо! - person yahya; 20.08.2013