таймер java TimerTask несколько потоков

Я использую таймер и TimerTask для длительного опроса новых сообщений для приложения чата. Я хотел бы рассмотреть две "слегка" разные возможности:

1 : таймер объявлен как локальная переменная

public List<MessageBean> getLastMessages(...) {
    [...]
    Timer timer = new Timer(true); //**Timer declared as local variable**
    while (someCondiction) {
        MessagesTimerTask returnMessagesTask = new MessagesTimerTask([...]);
        timer.schedule(returnMessagesTask, 6000);
        synchronized (listMessageBean) {
            listMessageBean.wait();
            //notify is called in the MessagesTimerTask which extends TimerTask
        }
    }
}

*проблема: каждый раз, когда я вызываю метод, я вижу, что создается новый поток, [Timer-1], [Timer-2] и т. д.. И в окне отладки Eclipse все они, похоже, работают даже после getLastMessages(..) отделки работает и возвращает значение клиенту. Это может вызвать огромную проблему, если таймеры фактически используют потоки, и после нескольких транзакций сервер в конечном итоге будет потреблять все ресурсы машины.

2 : таймер объявлен как локальное поле

private final Timer timer = new Timer(true); //**Timer declared as local field**

public List<MessageBean> getLastMessages(...) {
    [...]
    while (someCondiction) {
        MessagesTimerTask returnMessagesTask = new MessagesTimerTask([...]);
        timer.schedule(returnMessagesTask, 6000);
        synchronized (listMessageBean) {
            listMessageBean.wait();
            //notify is called in the MessagesTimerTask which extends TimerTask
        }
    }
}

*проблема: каждый раз, когда я вызываю метод, используется один и тот же поток [Thread-1], но я не уверен, что если я сделаю два последовательных вызова, последний отменит / переопределит первый (класс @Autowired by spring)?

какие предложения ? Спасибо.

1 ответов


здесь исходный код на schedule способ:

190       public void schedule(TimerTask task, long delay) {
191           if (delay < 0)
192               throw new IllegalArgumentException("Negative delay.");
193           sched(task, System.currentTimeMillis()+delay, 0);
194       }

и sched способ:

386       private void sched(TimerTask task, long time, long period) {
387           if (time < 0)
388               throw new IllegalArgumentException("Illegal execution time.");
389   
390           // Constrain value of period sufficiently to prevent numeric
391           // overflow while still being effectively infinitely large.
392           if (Math.abs(period) > (Long.MAX_VALUE >> 1))
393               period >>= 1;
394   
395           synchronized(queue) {
396               if (!thread.newTasksMayBeScheduled)
397                   throw new IllegalStateException("Timer already cancelled.");
398   
399               synchronized(task.lock) {
400                   if (task.state != TimerTask.VIRGIN)
401                       throw new IllegalStateException(
402                           "Task already scheduled or cancelled");
403                   task.nextExecutionTime = time;
404                   task.period = period;
405                   task.state = TimerTask.SCHEDULED;
406               }
407   
408               queue.add(task);
409               if (queue.getMin() == task)
410                   queue.notify();
411           }
412       }

отсюда вы можете ясно видеть, что очередь используется для хранения задач внутри, что означает, что более поздние задачи не будут перезаписывать более ранние. Если вы также проверяете mainLoop метод в файле вы можете видеть, что он берет задачи из очереди один за другим, упорядоченные по их расписанию, и выполняет их.

так что не надо быть проблемой, чтобы запланировать несколько задач на одном и том же