我知道使用Timer和TimerTask不再是当前被接受的做法(一些人建议使用线程,其他人建议使用ScheduledExecutorService或其变体),因此这个问题不是关于良好编程实践,而是关于实际错误或异常的可能性。
基本上,我有一个servlet,它保持一个运行中的计数器(这是一个静态日历对象),每秒钟增加一次。当达到指定的截止时间时(默认为10分钟),我从我的应用程序向NIST时间服务器发出调用以获取当前时间,然后将其用于重新设置我的计数器。
相同的TimerTask定义的方法会每秒钟增加一次计数器,也必须在每次我向NIST服务器发出调用(每10分钟)时暂停并重新安排。我尝试在调用NIST服务器之前取消/暂停现有的Timer/TimerTask对象,并在调用之后重新安排TimerTask,但没有成功。
从这个过程中产生的异常在这里描述: 当需要多次设置和取消时,如何在Java中使用计时器? 可以说,无论是TimerTask还是Timer都不能被多次调度,即使使用purge()或cancel()也只能将这些对象设置为Java垃圾回收的候选对象。
使用wait()和notify()会导致同步异常,而我不幸的是没有时间去解决,因此我的线程实验最初失败了。
最终我做的事情是:
基本上,我有一个servlet,它保持一个运行中的计数器(这是一个静态日历对象),每秒钟增加一次。当达到指定的截止时间时(默认为10分钟),我从我的应用程序向NIST时间服务器发出调用以获取当前时间,然后将其用于重新设置我的计数器。
相同的TimerTask定义的方法会每秒钟增加一次计数器,也必须在每次我向NIST服务器发出调用(每10分钟)时暂停并重新安排。我尝试在调用NIST服务器之前取消/暂停现有的Timer/TimerTask对象,并在调用之后重新安排TimerTask,但没有成功。
从这个过程中产生的异常在这里描述: 当需要多次设置和取消时,如何在Java中使用计时器? 可以说,无论是TimerTask还是Timer都不能被多次调度,即使使用purge()或cancel()也只能将这些对象设置为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();
}
我已经在几个晚上以10分钟和1分钟的间隔在NIST服务器调用之间运行了这段代码,并且它运行得很顺畅。
所以,在长时间的引言之后(感谢您的耐心等待),我的问题是:如果我继续使用当前的代码,是否会在长期内造成任何损害?如果我在一个月或六个月的时间内不断制作新的TimerTask和Timer对象,同时将旧的对象置空,那么是否会导致服务器内存不足?Java的垃圾回收机制是否足够强大,能够处理这种使用方式?是否会发生其他可怕的事情?
非常感谢您的时间, - Eli