线程中的Java:Thread.sleep():无等待

线程中的Java:Thread.sleep():无等待,java,multithreading,junit,sleep,Java,Multithreading,Junit,Sleep,我有一个线程不睡眠的问题。 我不能把我的全部密码都放在这里。所以,为了重现,这里有一个等待5秒的基本代码 try { int millisec = 5000; System.out.println(new Date()); System.out.println("We wait " + millisec + " milliseconds"); Thread.sleep(millisec); System.out.println(new Date()); }

我有一个线程不睡眠的问题。
我不能把我的全部密码都放在这里。所以,为了重现,这里有一个等待5秒的基本代码

try {
    int millisec = 5000;
    System.out.println(new Date());
    System.out.println("We wait " + millisec + " milliseconds");
    Thread.sleep(millisec);
    System.out.println(new Date());
} catch (Exception e) {
    e.printStackTrace();
}
输出:

2013年8月22日星期四20:01:42 CEST
我们等待5000毫秒
2013年8月22日星期四20:01:47 CEST

一切正常。
但是当我把这个代码放在一个线程中,没有睡眠。此代码的示例:

try {
    Thread aThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                int millisec = 5000;
                System.out.println(new Date());
                System.out.println("We wait " + millisec + " milliseconds");
                Thread.sleep(millisec);
                System.out.println(new Date());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    aThread.start();
} catch (Exception e) {
    e.printStackTrace();
}
输出:

2013年8月22日星期四20:07:30 CEST
我们等待5000毫秒

…除此之外,线程被终止。
我不明白为什么。拜托,有什么想法吗

编辑:我使用Eclipse和JUnit进行测试。

编辑:

问题是JUnit是如何工作的。它不知道后台线程已经生成,所以当测试线程完成时,它会杀死其余线程而不等待它们


当我在一个小的
main()
类中尝试时,您的代码正确地吐出了两个日期行。以下是一些可能的原因,说明您在应用程序中看不到输出的原因:

  • 生成aThread的线程本身可能是守护进程线程。因此,
    aThread
    是守护进程,因为它的守护进程状态是从生成线程的状态获取的。如果JVM在第二个
    System.out.println(…)
    之前完成,则
    aThread
    将被终止。如果对此有疑问,您应该:

    Thread aThread = new Thread(new Runnable() {
    ...
    // ensure the deamon flag is off _before_ we start the thread
    aThread.setDaemon(false);
    aThread.start();
    
  • 另一种可能性是,在第二个
    println(…)之前,实际上有东西正在关闭
    System.out
    。不太可能,但可能。您是否使用关机挂钩进行清理

  • 第三种可能是输出实际上正在打印,但IDE或控制台不知何故没有显示输出

  • 另一种可能性是,
    System.out.println(…)引发了一个
    IOException
    。检查
    System.out.checkError()
    的值以查看它是否为
    true
    ,这可能很有趣,尽管我不确定接下来如何显示它

要尝试的一件事是创建一个临时文件,而不是打印输出。比如:

new File("/var/tmp/" + System.currentTimeMillis()).createNewFile();
然后您应该在
“/var/tmp”
(或操作系统上的临时目录)中看到2个文件

您还应该尝试将
System.out
更改为
System.err
,以查看是否有任何更改。怀疑但值得一试


如果这些都不能很好地工作,那么JVM将被强制杀死,因此它无法等待后台线程。

我认为您没有在主线程中调用join()(如果您使用JUnit,那么线程将调用测试用例并创建线程对象)

你的进程本身是否在5秒后仍然有效?你的代码对我有效。你确定你的IDE没有切断输出或其他什么吗?对我来说也很有效,清理后再试一次。这应该不是必要的,但为了安全起见,试着在睡眠后添加一些println语句(只是打印一堆垃圾)。也许您的控制台出于某种原因正在缓冲输出。我使用Eclipse和Junit进行测试。如果您觉得合适,问题出在我的IDE中。我来看看。谢谢你的及时回复!可能性1:aThread.setDaemon(false)添加,对我来说没有更改。可能性3:是的,我使用Eclipse和JUnit,这可能是原因。谢谢实际上还有另一种(不太可能的)可能性:一个
错误
被抛出到某个
catch(异常e)
没有捕获到的地方,线程被终止得非常好@Katona。不太可能,但可能。
System.out.println(…)
可能还引发了一个正在捕获和阻止的内部异常。我加了一个,还有一个。如果使用JUnit4
@Test(timeout=…)
timeout
规则,则基于整个测试用例在守护进程线程中运行。您是对的,在启动后为JUnit测试添加
aThread.join()
。不幸的是,我不能把它放在我的生产应用程序中。感谢您的帮助。
Thread.join
如果您有一个工作线程,则可以使用其他类似的工具。