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

时间:2013-08-22 18:32:38

标签: 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());
} catch (Exception e) {
    e.printStackTrace();
}

输出:

Thu Aug 22 20:01:42 CEST 2013
我们等待5000毫秒
8月22日20:01:47 CEST 2013年

一切都很好。
但是当我把这段代码放在一个线程中时,没有睡觉。使用此代码的示例:

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();
}

输出:

Thu Aug 22 20:07:30 CEST 2013
我们等待5000毫秒

......没有别的,线程终止了。 我不明白为什么。请问,有什么想法吗?

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

2 个答案:

答案 0 :(得分:5)

修改

问题是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();
    
  • 另一种可能性是,在第二个System.out之前,某些内容实际上正在关闭println(...);。不太可能,但可能。您是否正在使用关闭挂钩进行清理?

  • 第三种可能性是输出实际上正在打印,但您的IDE或控制台在某种程度上不显示输出。

  • 另一种可能性是System.out.println(...);投掷IOException。检查System.out.checkError()的值以查看它是否为true可能会很有趣,但我不确定您将如何显示它。

要尝试的一件事是创建一个临时文件而不是打印输出。类似的东西:

new File("/var/tmp/" + System.currentTimeMillis()).createNewFile();

然后你应该看到"/var/tmp"中的2个文件(或者操作系统上的临时目录所在的位置)。

您还应该尝试将System.out更改为System.err,看看是否会发生任何变化。令人怀疑,但值得一试。

如果这些不能正常工作,那么有些东西会强行杀死JVM,因此无法等待后台线程。

答案 1 :(得分:1)

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