4

我有线程不睡觉的问题。
我不能把我的整个代码放在这里。所以,要重现,这是一个等待 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 进行测试。

4

2 回答 2

5

编辑:

问题原来是 JUnit 是如何工作的。它不知道产生了后台线程,因此当测试线程完成时,它会杀死其余线程而不等待它们。


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

  • 产生的线程aThread可能是一个守护线程本身。因此aThread是守护进程,因为它的守护进程状态是从生成线程的状态中获得的。如果 JVM在2号之前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在 2nd 之前关闭println(...);。不太可能但可能。您是否完全使用关闭挂钩进行清理?

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

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

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

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

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

您还应该尝试更改System.outSystem.err查看是否会改变任何内容。值得怀疑但值得一试。

如果这些都不能正常工作,那么某些东西正在强行杀死 JVM,因此它不能等待后台线程。

于 2013-08-22T18:50:49.000 回答
1

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

于 2013-08-23T02:29:25.663 回答