我知道使用Timer和TimerTask不再是当前接受的做法(有些人建议使用线程,其他人建议使用ScheduledExecutorService或其变体),所以这个问题不是关于良好的编程习惯,而是关于实际的可能性错误或异常。
基本上,我所拥有的是一个servlet,它保持一个运行计数器(它是一个静态Calendar对象),每秒递增一次。当达到指定的截止日期时(默认情况下我们达到10分钟),我从我的应用程序拨打NIST时间服务器来获取当前时间,然后我用它来重新设置我的计数器。
每次调用NIST服务器时,每隔10分钟,同一个TimerTask定义的计数器(每秒递增一次)也是必须暂停和重新调度的方法。在 NIST服务器调用之前暂停/取消现有的Timer / TimerTask对象并在调用之后重新调度TimerTask 时,我未成功。
此处描述了由此产生的异常: How do I use a timer in Java when required to set and cancel multiple times?
可以这么说,即使使用purge()或者cancel(),TimerTask和Timer都不能被多次调度,这似乎只适合将这些对象设置为符合Java垃圾回收的条件。
使用wait()和notify()导致同步异常,遗憾的是,我没有时间弄清楚,所以我最初的线程实验是失败的。
我最终做的是:
secondTickerTask.cancel();
secondTicker.purge();
secondTicker.cancel();
secondTickerTask = null;
secondTicker = null;
Date newCurrentTime = getNistTimeFromFirstWorkingServer();
// Save new date to current time, reset second counter.
setCurrentTimeAndDeadline(newCurrentTime);
startSecondIncrementTimer(newCurrentTime);
secondTicker = new Timer();
secondTickerTask = new TimerTask(){
public void run(){
incrementCurrentTimeAndTestDeadline();
}
我在NIST服务器调用之间以10分钟和1分钟的间隔过夜几次运行此代码,并且运行顺利。
所以,经过长时间的启动(感谢您的耐心),这就是我的问题:目前被迫使用我拥有的代码,是否有任何可能导致长跑?如果我继续制作新的TimerTask和Timer对象,同时忽略旧的那些,让我们说,一个月或六个月的一段时间,我会强制服务器耗尽内存吗? Java的垃圾收集是否足够强大以处理这种用途?还有其他可怕的事情发生吗?
非常感谢你的时间, - Eli
答案 0 :(得分:2)
Java将很好地处理计时器任务的创建和放弃。您需要确保在完成计时器时丢弃对计时器的所有引用,这看起来正在进行,然后当GC运行时它将清除计时器引入的任何垃圾。
你很安全。
您应该注意到,在很长一段时间内,某些Java进程往往会分配内存,直到达到-Xmx
限制为止。这并不意味着存在问题(因为该空间将由GC重用),但这也意味着,如果您希望长时间运行的Java进程具有相对较小的占用空间,则不应指定{{比你实际需要的要大得多。