线程在 JUnit 中行为异常

2022-09-02 20:28:55

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

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之间的输出。如果我将此代码转换为常规类并运行它,它可以正常工作。有没有人知道我在这里错过了什么?

谢谢, - 安德鲁。


答案 1

您可以使用 来防止测试在新线程完成其任务之前完成: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 将终止。您可能会期望,只需调用线程即可防止 JVM 在任务完成之前退出。但是,junit 会在主线程完成时调用 System.exit()。t.setDaemon(false)

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

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


答案 2

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

因此,您会看到“线程的输出”,直到它被杀死。如果要等待线程完成,可以使用(在调用后立即)使其等待结果或在某些对象上使用。Thread.joinThread.start()wait-notify

另外,发现这个问题:JUnit终止子线程