This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
While going throgth Khalid Mughal Thread topics, i came across the following question.
(a) The first number printed is 13 (b) The number 14 is printed before the number 22 (c) The number 24 is printed before the number 21 (d) The last number printed is 12 (e) The number 11 is printed before the number 23
The answer is b and d. the explaination given in the answer is: The inner createThread() call is ecaluated first, and will print 23 as the first number. The last number the main thread prints is 14. After the main thread ends, the thread created by the inner createThread() completes its join() call and prints 22. After this thread ends, the thread created by the outer createThread() call completes its join() call and prints the number 12 before the program terminates.
sorry for incomplete post. I am confused about the join() method execution and how come 14 printed before 22 and the last number printed 12 where as System.out.println(i+4); is there after the start() call.
I am confused about program execution.
Thanks in advance.
Joined: Dec 20, 2001
Hmmm. This one really is a bear and it took me a little while, but let me try to walk you through the path of execution. Forgive me if this explanation gets rather long-winded. We'll start in the main method:
This method does a double-invocation of the method createThread. Obviously, before we can complete the first evocation of that method, we must evaluate all of the arguments that will be passed to that method. Therefore, we must first evaluate "createThread(20...)". That puts us in this block:
The first thing we do is create a new Thread object and assign a reference to that object to the variable t2. Note, however, that we have not yet started that thread.
The next line that we execute is this one:
The variable i, in this case, is 20, so we spit out 23 as our first line of output. Knowing that our first value printed will be 23, we know that option A is incorrect. We also know that option E is incorrect because, if 23 is the first value printed, there's no way 11 could be printed prior to that. Moving on to the next line, we execute this:
Okay, now that we've started a second thread, things can get a little tricky. At this point, we have no idea which thread is going to execute next, the main thread or the newly spawned thread. It could be either one. For the sake of argument, let's say that the new thread executes next. That means we're going to execute this:
That causes 21 to be printed to output. Next, we execute the following line:
A invocation of the join method causes the currently executing thread to wait until the named thread is finished executing. At this point, we know that this thread will stop and we'll head back to the main thread. That puts us at this line:
That line, of course, will spit out 24.
Now, let's stop for a second. I pointed out earlier that we didn't know which thread was going to execute first and then I picked one to execute first. I have no way of knowing if that assumption was correct or not. Quite possibly, my assumption would be correct on some platforms and incorrect on others. So, what does that mean to us?
Well, in this case, that just means that we don't know when the number 21 is going to be printed. It might be printed before 24, it might be printed after. We just don't know. All we do know is that, after that new thread prints 21, it's going to wait until the main thread is finished. Based on that, we know that option C is incorrect - we have no assurance that 24 will be printed before 21. It might be, but it might not be.
Moving on with the main thread, we execute this line:
This completes our method invocation and allows us to invoke createThread a second time. This second time, though, we're passing a reference to this new thread (the one that is waiting for the main thread to finish) rather than a reference to the main thread.
Now that we've begun our new method invocation, create a new instance of another Thread object but, once again, we don't start it right away. Instead, we execute this line:
This time, we passed the value 10 in the argument i, so we print 13. Then, we execute this:
Now we've started off yet another thread. Just like the last time, we don't know yet whether or not this new thread will begin executing right away or if the main thread will begin executing. In fact, if the first thread we created hasn't executed yet, we might end up executing that thread now. :roll:
Let's make another assumption at this point. We'll assume that this new thread is going to execute now. That means that we execute this line:
With i being equal to 10, we print 11. We then execute this line:
Okay, here's the kicker. This new thread is going to wait for thread t1 to complete execution. Which thread is t1? Well, that's the thread we created the first time we executed this method. What's that thread doing? Well, it's waiting for the main thread to complete because it alerady invoked join on that thread.
So what do we have now? We have 2 stalled threads. The first thread is waiting for the main thread and the second thread is waiting for the first thread. That means that we know the main thread is going to execute next. We know that for sure. That puts us here:
This, of course, prints 14. We then complete the execution of this method and the main thread terminates.
Now that the main thread has terminated, the first thread we created can continue execution. Note that the second thread we created is still stalled because it is waiting for the first thread to finish.
With the first thread running again, we execute this line:
That line prints 22 to output. From this, we can see that, no matter what, the number 14 is going to print prior to 22 so option B is correct.
Once that line is executed, our first thread completes and our second thread can continue on happily. This line is executed:
And we print 12 to output. That's the final line to be executed. Therefore, we know that option D is correct. 12 is the last thing to be printed. Always.
This is a pretty tough question and I hope you followed my explanation. If you're still confused, let me know.
Wow, This was like a debugging session. I hope tough questions like this are not the norm.
How good must one be with Threads for certification. Should one read up on Threads thoroughly? There is this book on Java threads by Scott Oaks and henry Wong. I suspect it is too exhaustive and some of the exqmples are really hard to follow.
Is it okay one has read up from Java tutorial and the certification book.
Joined: Aug 29, 2003
The explaination given by you is really good
It solved my confusion. I appreciate the time and efforts you put to resolve my problem.
Thanks again. Saiprasad
Joined: Dec 20, 2001
Originally posted by Swamy Nathan: Wow, This was like a debugging session. I hope tough questions like this are not the norm.
This question is a real beast. I wouldn't expect such problems to be on the exam. The folks at Sun realize how long it takes to dissect a problem like this and certainly wouldn't put such a question on the exam. However, in terms of practice, this is a great question. If you can figure this one out, you're home free.
Though something this hard may not be on the exam it helps point out the need to have a plan for how you approach the exam questions. From the length of Corey's explanation, it is clear that this code is complicated. Handling the question from simple to hard issues lets you get through it the fastest, once you are sure you understand the basics of the code.
If it were an exam question, a simple read through renders options A & E as false, the linear path through the code establishes 23 will be printed before any thread starts. Second, since printing 24 and printing 21 are the next actions after the first thread starts, option C is impossible to determine because it will depend on the JVM scheduler.
Without even getting into the thread join behaviors, only two options are left, which can then be more easily validated.
On some questions, however, you do need to breakdown into a complete linear walkthrough tracking variable values, etc. before you can determine which answers are correct.