线程在JUnit中表现奇怪

时间:2013-05-17 19:33:02

标签: java multithreading junit

我正在尝试编写需要多线程的单元测试。但是,似乎线程只是停止执行的一部分。请考虑以下代码:

public class Test {
    @org.junit.Test
    public void TestThreads() {
        new Thread(new Runnable() {
            public void run() {
                for (int i = 1; i < 1000; i++) System.out.println(i);
            }
        }).start();
    }
}

如果我运行此单元测试,它通常会停止在140-180之间显示输出。如果我将此代码转换为常规类并运行它,它可以正常工作。有没有人知道我在这里缺少什么?

谢谢, - 安德鲁。

3 个答案:

答案 0 :(得分:23)

您可以使用Thread.join()来阻止测试在新线程完成任务之前完成:

@org.junit.Test
public void TestThreads() throws InterruptedException {
    Thread t = new Thread(new Runnable() {
        public void run() {
            for (int i = 1; i < 1000; i++) System.out.println(i);
        }
    });
    t.start();
    t.join();
}

通常,JVM将在最后一个非守护程序线程终止时终止。您可能希望在线程上简单地调用t.setDaemon(false)会阻止JVM在任务完成之前退出。 但是,当主线程完成时,junit将call System.exit()。

正如Gus在评论中指出:“你需要join()因为start()不会阻止”。

他是正确的,你也可以在这个最小的例子中调用run()。但是,我假设您正在启动一个线程,因为您希望它与另一个线程并发运行。在线程上调用run()被FindBugs标记为可能的错误 - 如果你只是要调用run(),你可能只想实现Runnable而不是使用Thread。

答案 1 :(得分:6)

TestThread函数中,JUnit无法告诉您生成了一个新线程。一旦函数结束(到达最后一行)并且不知道线程,它就会回收它在函数中创建的任何对象。

因此,您可以看到Thread的输出,直到它被杀死。如果您想等待线程完成,可以使用Thread.join(在致电Thread.start()之后)使其等待结果或在某个对象上使用wait-notify

另外,发现了这个问题:JUnit terminates child threads

答案 2 :(得分:0)

运行测试的父线程可能正在完成。如果可以避免它,那么不要在测试中创建新线程。我将创建一个实现runnable的新类,然后测试该类,我只是在该对象上调用run。您不应该在测试过程中测试线程调度。希望java语言开发团队能够覆盖:)