Issue
I have a small test using just two threads as follows:
import static java.lang.System.out;
@Test
public void testTwoSimpleThreads() {
doInParallelAsync(() -> {
out.println("First Ok");
},
() -> {
out.println("Second Ok");
});
}
private void doInParallelAsync(Runnable first, Runnable second) {
new Thread(() -> {
first.run();
}).start();
new Thread(() -> {
second.run();
}).start();
}
Sometimes the output will only include one of them before I introduced join()
after they're started.
Two different outputs I encountered so far:
one
First Ok
Two
First Ok
Second Ok
I know the println()
is synchronized and also I know the threads created by main thread are user threads in default and user threads will not exit until they finish.
Though I am using @Test, I tested it that they're non-daemon as expected.
is a daemon thread if and only if the creating thread is a daemon
And
The Java Virtual Machine continues to execute threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
UPDATED
Actually I know what the answers point out, I wonder why the output disappear?
Questions I need to ask:
The pipeline closed by the main thread?
Why? Is it because each pipeline is bond to one thread independently? Not shared? (that the pipeline won't be closed until the last thread finish just like the reference counting - the file will not be deleted until no one is using it)
The last question: is it controlled by JVM or dependent upon the OS?
It seems the pipeline is closed by the @Test
I mentioned. Thank you, @meriton for pointing it out.
Conclusion
When I tried this method in an ordinary main()
, and directly invoke System.exit(0);
just right after the start()
, the output is quite the same as that when using @Test
.
When using @Test
(Junit), the threads will not be waited. For more details, please check JUnit test not executing all threads created within the test and JUnit terminates child threads.
And here is an explanation from @Alex Lockwood which I personally prefer:
JUnit is a unit testing framework... as with the Android framework, it has a main thread from which it will call user-defined unit test methods. When a unit test returns, JUnit immediately invokes the next unit test method (or exits completely if there are no more unit test methods to call). JUnit doesn't know anything about the background threads you create/start, so you can't assume that it will sit around and wait for them to finish.
Solution
Might the test runner invoke System.exit()
after all tests have run? Can you reproduce the partial output if you convert the test into an ordinary main()
method?
(I'd try myself, but was unable to reproduce a partial output when running this as a JUnit test in eclipse)
... and no, System.out
is a static field, and hence shared by all threads. Exiting the main thread does not close the stream.
Answered By - meriton