java Timer TimerTask多线程

标签 java multithreading timer timertask

我正在使用 Timer 和 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],但我不确定是否连续调用两次,后者将取消/覆盖前者(这个类是 spring 的@Autowired)?

有什么建议吗? 谢谢。

最佳答案

这是 source code 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 方法,您可以看到它从队列中按计划时间一个接一个地获取任务并执行它们。

所以在同一个 Timer 对象上安排多个任务应该不是问题。

作为旁注,请考虑将 Timer 替换为自 Java 1.5 起可用的 ScheduledThreadPoolExecutor

关于java Timer TimerTask多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12015642/

相关文章:

java - 在 Java 中使用 Timer 重置矩形位置

java - 在 Java 中为 OpenSSL 格式化 RSA key

c - 锁定 api 的正确约定是什么?

C# 在使用 ThreadPool 时,我可以将多个数据传递到我的目标方法吗?

java - 同一线程能够在同一对象上执行两个同步方法

java - Swing 定时器的问题

java - 从数据库中检索 java 中的完整日期

java - 无法使用java从sqlserver获取阿拉伯字母

java - Google App Engine 本地数据存储控制台

c++ - Windows WaitableTimers - 找不到错误