1

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.

non-daemon

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:

  1. The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.

  2. 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:

  1. The pipeline closed by the main thread?

  2. 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)

  3. 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.

14
  • output will only include one Always the first or sometimes the second? Commented Jun 27, 2018 at 1:25
  • 1
    You're not showing what out is or how you create it. Please add that. Commented Jun 27, 2018 at 1:31
  • @ScaryWombat I just updated my question, would you please take a look? Thank you ~ Commented Jun 27, 2018 at 1:40
  • 1
    @Hearen Yes agreed, but as main thread has finished out will not work any more. For instance try the same thing on Jshell and you will always get both the output, but the second output sometimes go as another command, that is because main thread didn't wait for child threads to close and completed and hence jshell moved to next command line on which you can see the other output Commented Jun 27, 2018 at 1:53
  • 1
    Please read and reply to the second top comment above. I am guessing that the main thread opens and implicitly closes the out Commented Jun 27, 2018 at 1:54

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, meriton. I just cannot re-produced that in-complete output any more in plain main program. It seems it's the runner close it.
2

Thats because you started them on a different thread and the main thread do not wait for child threads to complete and will close its execution immediately after last line.

So, by that time if Thread 1 is executed Output will be:

First Ok 

If Thread 2 is executed:

Second Ok 

And if by luck both got executed then

First Ok Second Ok 

or

Second Ok First Ok 

By providing join, you are asking main thread to wait for the child thread to be completed and hence both the outputs.

-- EDITED --

This doesn't mean that the child threads were terminated, they still completed their execution but you may not be able to see the results as outstream may have been closed or released by that time

If you execute the same command on Jshell, you will always get the second output, but sometimes it come in as another command, because as soon as main thread completes, Jshell moves to next command line:

enter image description here

5 Comments

Thanks for the reply, but it actually doesn't solve my problem.
@Hearen why not? You need to wait for each Thread to terminate before terminating the main thread. You can do this by using join or a countdownLatch
@ScaryWombat I updated my question. Would you please check it? The termination time is understood but my confusion lies not here.
@Hearen I think you need to rephrase your question, if you are asking something different, because for now, it seems that you are asking why the output was not shown for both the threads and I have already shared the reason for the same
@AmanChhabra Thanks for the digging. Sorry to say this: still not answering my updated questions. Thank you, Aman.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.