线程在JUnit中表现奇怪

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

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

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

谢谢, – 安德鲁。

您可以使用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将调用 System.exit()。

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

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

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

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

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

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