Thread.sleep() 已挂起?

2022-09-02 10:33:26

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

while (true) {
  // check db for new jobs and 
  // kick off thread if necessary
  try {
    Thread.sleep(1000);
  } catch(Throwable t) {
    LOG.error("", t);
  }
}

此代码已运行数月。就在昨天,我们开始遇到一个问题,我们的一个服务器似乎挂在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)

Scheduler.java:400 是上面的 Thread.sleep 行。jconsole输出不会像我预期的那样每秒递增“等待总数”。事实上,它根本没有改变。我甚至关闭了jconsole并重新启动它,希望这也许会强制刷新,但只是再次获得相同的数字。我不知道除了jvm错误地挂在sleep命令上之外,还有什么其他解释。然而,在我的岁月里,我对jvm的问题很少,以至于我认为它一定是我的疏忽。

注意:另一件需要注意的事情是没有其他线程处于活动状态。IOW - CPU 几乎空闲。我在某处读到,如果另一个线程处于活动状态,Thread.sleep可能会合法地挨饿,但这里的情况并非如此。

太阳能版本:

$ uname -a
SunOS xcmst 5.10 Generic_141415-08 i86pc i386 i86pc

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)

答案 1

除了bdonlan提到的内容之外,您可能还想研究SchudmentThreadPoolExecutor。我从事一种非常相似类型的项目,这个对象使我的生活更轻松,这要归功于这个小片段。

ScheduleAtFixedRate

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

我希望这有帮助!


答案 2

您是否依赖系统刻度计数来单调增加?

根据我从某人那里听到的情况,系统勾选结果(偶尔)会向后退一两个刻度。我自己还没有经历过,但如果你依赖这个,这能解释一下发生了什么吗?

编辑:

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