最近在工作中遇到了一个比较奇怪的问题,产品运行过程中,修改了系统时间之后发现,如果是将系统时间修改至当前时间之后就是正常的,如果是修改到当前时间之前,所有的实时数据就推送不到页面上,经过调试发现确实不再有时间的实时数据推送到界面上,这时就需要重新启动一下服务,就正常了。
针对这个问题做了一下分析和解决,记录一下,如果以后有遇到这种问题的童鞋们就可以轻松知道为什么会出现这种现象了,并且会Timer这个类会有更加深入的了解。
其实通过产品本身的实现就是通过Timer这个类实现的,索性就直接找到这个类的实现来看一下:
currentTime = System.currentTimeMillis(); executionTime = task.nextExecutionTime; if (taskFired = (executionTime<=currentTime)) { if (task.period == 0) { // Non-repeating, remove queue.removeMin(); task.state = TimerTask.EXECUTED; } else { // Repeating task, reschedule queue.rescheduleMin( task.period<0 ? currentTime - task.period : executionTime + task.period); } }
从这段代码可以看出,TimerTask执行的条件是(executionTime<=currentTime)。其中executionTime取自TimerTask,而currentTime来自系统时间。原因就在于此,currentTime因为修改系统时间而提前了,所以这个条件(executionTime<=currentTime)永远也不会达到,TimerTask将不会被执行。
所以通过这段代码来看,如果系统时间修改到当前时间之后,不会影响Timer的执行;但是如果系统时间修改到当前时间之前,就会导致Timer挂起。
如果是修改到当前时间之前,Timer处于挂起状态的时候就需要重新启动一下服务,来重新出发Timer定时任务。
这种情况正好是产品中用到的TimerTask所导致的,所以如果有时候遇到问题需要去好好研读一下JDK中的代码,里面有很多内容需要我们去理解,只有把这些基础的内容夯实,才能在遇到问题的时候不会毛手毛脚,四处乱找。