繁体   English   中英

java Timer TimerTask多线程

[英]java Timer TimerTask multiple threads

我正在使用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 Debug窗口中,即使在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 )?

有什么建议 ? 谢谢。

以下是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对象上安排多个任务应该不是问题。

作为附注,考虑使用自Java 1.5以来可用的ScheduledThreadPoolExecutor替换Timer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM