线程在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语言开发团队有这个涵盖:)