Thread.sleep()挂了吗?

and*_*bd1 20 java sleep

这是我的简单代码,每秒循环(不需要精确)并在必要时启动作业:

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)

Sha*_*ded 7

除了bdonlan提到的,你可能想要查看ScheduledThreadPoolExecutor.我在一个非常类似的项目上工作,这个对象让我的生活更轻松,这要归功于这个小片段.

ScheduleAtFixedRate

如果此任务的执行时间超过其周期,则后续执行可能会延迟,但不会同时执行.

我希望这有帮助!


Meh*_*dad 5

您是否依赖系统滴答计数来单调增加?

根据我从经验丰富的人那里听到的消息,它(偶尔)会发生系统节拍倒退一两个滴答声.我自己还没有经历过,但如果你依赖于此,这可能会解释发生了什么吗?

编辑:

当我说System.currentTimeMillis(),我相信我错了.我认为这System.currentTimeMillis()类似于Windows的GetTickCount()功能(即它测量的时间与系统时间无关),但事实上,情况似乎并非如此.所以当然它可以改变,但这不是我的观点:显然,系统计时器测量的滴答计数可以倒退一两滴,甚至忽略系统时间的变化.不确定这是否有帮助,但感谢Raedwald指出系统时间变化的可能性,因为那不是我的意思.

  • 在Unix系统上,使用`date`命令可以向后设置任意数量的时钟.也许有人在你的进程运行时改变了时钟? (2认同)