这是我的简单代码,每秒循环(不需要精确)并在必要时启动作业:
while (true) {
// check db for new jobs and
// kick off thread if necessary
try {
Thread.sleep(1000);
} catch(Throwable t) {
LOG.error("", t);
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码已经好几个月了. 就在昨天,我们开始出现问题,其中一个服务器似乎挂在Thread.sleep(1000)方法中.IOW - 已经过了一天而且Thread.sleep还没有返回.我启动了jconsole并获取有关该线程的信息.
Name: Thread-3
State: TIMED_WAITING
Total blocked: 2 Total waited: 2,820
Stack trace:
java.lang.Thread.sleep(Native Method)
xc.mst.scheduling.Scheduler.run(Scheduler.java:400)
java.lang.Thread.run(Thread.java:662)
Run Code Online (Sandbox Code Playgroud)
Scheduler.java:400是上面的Thread.sleep行.按照我的预期,jconsole输出不会每秒增加"Total wait".事实上,它根本没有变化.我甚至关闭了jconsole并重新启动它,希望可能会强制刷新,但只会再次获得相同的数字.我不知道除了jvm错误地挂在sleep命令上之外还有什么其他的解释.然而,在我这些年里,我对jvm的问题很少,我认为这一定是我的疏忽.
注意:另外需要注意的是没有其他线程处于活动状态. IOW - cpu几乎空闲.我读到某个地方,如果另一个线程处于活动状态,Thread.sleep可能会被合法地饿死,但事实并非如此.
solaris版本:
$ uname -a
SunOS xcmst 5.10 Generic_141415-08 i86pc i386 i86pc
Run Code Online (Sandbox Code Playgroud)
java版本:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)
Run Code Online (Sandbox Code Playgroud)
除了bdonlan提到的,你可能想要查看ScheduledThreadPoolExecutor.我在一个非常类似的项目上工作,这个对象让我的生活更轻松,这要归功于这个小片段.
如果此任务的执行时间超过其周期,则后续执行可能会延迟,但不会同时执行.
我希望这有帮助!
您是否依赖系统滴答计数来单调增加?
根据我从经验丰富的人那里听到的消息,它(偶尔)会发生系统节拍倒退一两个滴答声.我自己还没有经历过,但如果你依赖于此,这可能会解释发生了什么吗?
当我说System.currentTimeMillis()
,我相信我错了.我认为这System.currentTimeMillis()
类似于Windows的GetTickCount()
功能(即它测量的时间与系统时间无关),但事实上,情况似乎并非如此.所以当然它可以改变,但这不是我的观点:显然,系统计时器测量的滴答计数也可以倒退一两滴,甚至忽略系统时间的变化.不确定这是否有帮助,但感谢Raedwald指出系统时间变化的可能性,因为那不是我的意思.
归档时间: |
|
查看次数: |
11233 次 |
最近记录: |