Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread behaving strangely in JUnit

I'm trying to write a unit test that requires mulitple threads. However, it seems that the threads just stop part way through execution. Consider the following code:

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

If I run this unit test, it will generally stop displaying output somewhere between 140-180. If I convert this code into a regular class and run it, it works fine. Does anybody have any idea what I'm missing here?

Thanks, - Andrew.

like image 766
Andrew Clarke Avatar asked May 17 '13 19:05

Andrew Clarke


2 Answers

You can use Thread.join() to prevent the test from finishing before the new thread has completed its task:

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

Normally, the JVM will terminate when the last non-daemon thread terminates. You might expect that simply calling t.setDaemon(false) on the thread would prevent the JVM from exiting before the task is finished. However, junit will call System.exit() when the main thread has finished.

As Gus notes in the comments: "you need join() because start() doesn't block".

He's correct that you could also call run() in this minimal example. However, I assume you're starting a thread because you want it to run concurrently with another thread. Calling run() on a Thread is flagged up as a possible mistake by FindBugs - if you're just going to call run(), you'd probably just want to implement Runnable instead of using Thread.

like image 178
Martin Ellis Avatar answered Nov 02 '22 19:11

Martin Ellis


In the TestThread function, JUnit has no way of telling that you spawned a new thread. It reclaims any objects it created in the function as soon as the function ends (last line is reached) and doesn't know about the thread.

For this reason, you see Output from the Thread until it gets killed. If you want to wait for Thread Completion, you can use Thread.join (right after you call Thread.start()) to make it wait for the result or use wait-notify on some object.

Also, found this question: JUnit terminates child threads

like image 39
goblinjuice Avatar answered Nov 02 '22 19:11

goblinjuice