Java JUnit中行为异常的线程

Java JUnit中行为异常的线程,java,multithreading,junit,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.ou

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

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();
    }
}
公共类测试{
@org.junit.Test
公共void TestThreads(){
新线程(newrunnable()){
公开募捐{
对于(int i=1;i<1000;i++)System.out.println(i);
}
}).start();
}
}
如果我运行这个单元测试,它通常会停止显示140-180之间的输出。如果我将这段代码转换成一个常规类并运行它,它就可以正常工作。有人知道我错过了什么吗

谢谢,
-Andrew。

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

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

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


此外,还发现了以下问题:

您可以使用
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();
}
@org.junit.Test
public void TestThreads()引发InterruptedException{
线程t=新线程(新的可运行线程(){
公开募捐{
对于(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()
。但是,我假设您启动一个线程是因为希望它与另一个线程同时运行。在线程上调用
run()。IIRC,如果不打算同时执行任何操作,也可以使用Run()。@Gus在
线程
实例上使用
Run
是个坏主意。为什么?因为使用
run
不会使它成为线程,只是一个普通对象。谢谢,这正是问题所在。run()工作得很好,但否定了测试所需的多线程。您可能知道这是我第一次编写多线程Java程序。我想这取决于您是否打算测试该方法,或者说JUnit“deletes”对象有点误导,因为在Java中,无法显式删除对象。@Martin right。但是当不再需要对象时,JVM可以回收(GC)。测试完成后,JUnit会杀死线程,基本上是整个JVM,但这并不意味着JUnit会杀死一个对象实例。由于JVM退出,使用的每一个内存位都将被释放。它只调用System.exit。在我的答案中有一个指向来源的链接。