Volatile также полезно, когда вы хотите заставить компилятор не оптимизировать конкретную кодовую последовательность (например, для написания микропрограммы).
Вы не можете повторно использовать TimerTask, как это делаете здесь.
Соответствующая часть Timer :
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
//Right here's your problem.
// state is package-private, declared in TimerTask
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
Вам нужно будет реорганизовать свой код, чтобы что вы создаете новую TimerTask, а не используете ее повторно.
Мне кажется странным иметь TimerTask со своим собственным таймером внутри. Плохой дизайн. Я бы полностью разделил их и передал бы реализацию TimerTask таймеру, а всю эту логику возился с периодом внутри другого класса, который предоставляет интерфейс для этого. Пусть этот класс создаст экземпляры Timer и TimerTask и отправит их выполнять свою работу.