Timer 的使用陷阱
程序中涉及到任务调度功能,由于调度规则非常简单(在指定时间执行一次),所以就没有使用 Quartz 的必要。
还是切入正题吧,由于博主是一位菜鸟,在使用 Timer 的时候发现,程序的调度任务被完成之后,程序依然出现在进程中,没有被退出在多次 ps -axu | grep "xxx.jar"
之后,发现程序依然存在。然后菜鸟在eclipse
上检查了一下代码,确认没有异常代码之后,查看了服务器上打印出来的日志。日志正常,没有任何问题。
此时,需要祭出 java
程序员的杀手锏了。
杀手锏
jps -ml //找到目标进程 id
然后需要使用 jstack
查看该进程的相关情况
jstack -l [id] //生成进程dump
在生成的 dump 中,发现有大量 timer 线程处于WAITING
状态 in Object.wait()
看来是内部线程导致了程序的不结束。
查看 Timer 相关api,最终发现 Timer
的介绍
对 Timer 对象最后的引用完成后,并且 所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是这可能要很长时间后才发生。
没错,需要等待 gc
,但是程序如果任务完成,没有其他任何代码的执行之下,可能很难等到 虚拟机进行 gc 了。
一次服务器上的调度任务排查,就这样结束了。。。