【问题标题】:Java : Thread.sleep() in a thread : no waitJava:线程中的 Thread.sleep():无需等待
【发布时间】:2013-08-25 15:29:09
【问题描述】:

我遇到了线程不休眠的问题。
我不能把我的整个代码放在这里。所以,为了重现,这是一个等待 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 进行测试。

【问题讨论】:

  • 您的进程本身是否存活超过 5 秒?
  • 您的代码对我有用。您确定您的 IDE 没有切断输出或其他什么?
  • 对我也有用,清理并重试。
  • 这不是必须的,但为了安全起见,请尝试在睡眠后添加一些 println 语句(只是打印一堆垃圾)。也许您的控制台出于某种原因正在缓冲输出。
  • 我使用 Eclipse 和 Junit 进行测试。如果你没问题,问题出在我的 IDE 上。我去看看。感谢您的及时回复!

标签: java multithreading junit sleep


【解决方案1】:

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

【讨论】:

  • 你是对的,在开始解决JUnit测试后添加aThread.join()。不幸的是,我不能把它放在我的生产应用程序中。感谢您的帮助。
  • 如果您有一个工作线程,Thread.join 可以工作,否则 ConcurrentUnit 之类的东西可以提供帮助。
【解决方案2】:

编辑:

问题出在 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,因此它不能等待后台线程。

【讨论】:

  • 可能性1:aThread.setDaemon(false) 已添加,对我来说没有任何变化。
  • 可能性 3:是的,我使用 Eclipse 和 JUnit,这可能是原因。谢谢!
  • 实际上还有另一种(不太可能)的可能性:Error 被抛出某个未被catch (Exception e) 捕获的地方,线程被静默终止
  • 好一个@Katona。不太可能但可能。 System.out.println(...) 也可能引发了一个被捕获和阻止的内部异常。我已经添加了。
  • 还有一个。如果使用 JUnit4 @Test(timeout=...)TimeOut 规则,则基于 this 整个测试用例在守护线程中运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2021-11-10
  • 2015-07-04
相关资源
最近更新 更多