Java Thread.sleep()挂起了吗?

Java Thread.sleep()挂起了吗?,java,sleep,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); } } 这个代码已经运行了好几个月了就在昨天,我们开始出现问题,其中一台服务器似乎挂在线程中。sleep

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

while (true) {
  // check db for new jobs and 
  // kick off thread if necessary
  try {
    Thread.sleep(1000);
  } catch(Throwable t) {
    LOG.error("", t);
  }
}
这个代码已经运行了好几个月了就在昨天,我们开始出现问题,其中一台服务器似乎挂在线程中。sleep(1000)方法。已经过了一天了,睡眠还没有恢复。我启动了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)
java:400是上面的Thread.sleep行。jconsole输出并不像我期望的那样每秒递增“Total waitied”。事实上,这一点都没有改变。我甚至关闭了jconsole并重新启动它,希望这可能会强制刷新,但结果还是一样。除了jvm错误地挂起了sleep命令之外,我不知道还有什么其他解释。然而,在我的这些年里,jvm很少出现问题,我认为这一定是我的疏忽

注意:另外需要注意的是,没有其他线程处于活动状态。IOW-cpu几乎处于空闲状态。我在某个地方读到过,如果另一个线程处于活动状态,睡眠可能会被合理地剥夺,但这里的情况并非如此

solaris版本:

$ 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)
您是否依赖于系统滴答数单调增加

根据我从有经验的人那里听到的消息,系统会(偶尔)倒退一到两次。我自己还没有经历过,但如果你依靠这个,这能解释发生了什么吗

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

除了bdonlan提到的内容之外,您可能还想了解一下。我从事一个非常类似的项目,由于这个小片段,这个对象使我的生活变得更轻松

预定固定日期 如果此任务的任何执行时间超过其周期,则 后续执行可能会延迟开始,但不会同时执行 执行

我希望这有帮助

Thread.sleep()在Java编程中不是一个好的实践。只要谷歌“Thread.sleep()糟糕吗?”你就会明白我的意思

首先,它使程序的其他部分无法访问当前线程,特别是如果它是多线程的。也许这就是为什么你正在经历绞刑

其次,如果当前线程是EDT(事件调度线程),并且应用程序具有Swing GUI,那么这将是灾难性的

更好的选择是Object.wait():


也许您可以尝试Jconsole以外的另一个工具,首先确认它是sleep api中的块

例如,手动尝试使用jstack多次将其打印到文件并检查结果

或者使用更好的工具,例如Youkit(commercail),如果您的组织有深入分析应用程序的许可证,或者使用远程调试(可能无法在生产中)


或者,您可以检查“//check db for new jobs”代码是否在运行期间运行。通过检查日志、配置文件或任何其他方法取决于您的应用。。。。。。。。如果check db非常快,然后休眠1秒,那么很可能您总是在堆栈跟踪中看到休眠,只是因为比较的概率…

我知道您查看了jconsole,但是将信号3发送到进程(即kill-3)并在此处发布更多生成的线程转储可能会很有用。或者,如果你真的想深入细节,那么你可以考虑快速地继承一个或多个挂起进程的pStA/J堆栈转储,以显示线程真正的位置。有关如何将此信息与java线程转储关联的在线信息

另外,通过“我们的一台服务器”,您是说问题可以在一台服务器上重现,但在其他服务器上从未发生过?这表明该服务器存在问题。检查服务器上的所有内容是否相同,并且该硬件上是否没有任何问题

最后,这本身可能不是java问题。sleep(long)是一种本机方法(直接映射到底层操作系统的线程管理),因此请检查您的操作系统是否是最新的。

您是否考虑过使用&

下面是一个可能会有所帮助的简单片段

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class Example {

    public static void main(String args[]) {
        Timer timer = new Timer();

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Calendar instance = Calendar.getInstance();
                System.out.println("time: " + instance.getTime() + " : " + instance.getTimeInMillis());

                // check db for new jobs and
                // kick off thread if necessary
            }
        };

        int startingDelay = 0; // timer task will be started after startingDelay
        int period = 1000; // you are using it as sleeping time in your code
        timer.scheduleAtFixedRate(task, startingDelay, period);
    }

}
编辑

根据我所研究的讨论,
Thread.sleep()是代码设计糟糕的标志。
原因如下

  • …线程不会失去任何监视器的所有权(来自文档)
  • 阻止线程执行
  • 很明显,这并不能保证执行会在睡眠时间后开始
  • 对我来说,使用Thread.sleep()非常简单。有一个完整的包专门用于

哪一个比Thread.sleep()更好?这就引出了另一个问题。我建议您查看一下
Effective Java

一书中的Concurrency一章,您的日志是否显示来自
LOG.error
语句的任何内容?这可能是数据库代码中的死锁吗?@Freiheit-不,数据库中没有任何内容logs@Bobby-我不这么认为。即使是这样的话,这就是线程睡眠不会在这个线程中醒来的原因吗?”安德森BD1:你是否可以考虑运行dTrace/Strues来理解是什么导致了冻结?既然你看起来有
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class Example {

    public static void main(String args[]) {
        Timer timer = new Timer();

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Calendar instance = Calendar.getInstance();
                System.out.println("time: " + instance.getTime() + " : " + instance.getTimeInMillis());

                // check db for new jobs and
                // kick off thread if necessary
            }
        };

        int startingDelay = 0; // timer task will be started after startingDelay
        int period = 1000; // you are using it as sleeping time in your code
        timer.scheduleAtFixedRate(task, startingDelay, period);
    }

}