It's not a secret anymore!*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Joining Thread, Explanation required Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Joining Thread, Explanation required" Watch "Joining Thread, Explanation required" New topic
Author

Joining Thread, Explanation required

Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
The source of this code is Khalid Mughal : Chapter 9, Question 9:


Please guide me how things are going on!

Thanks and Regards,
cmbhatt


cmbhatt
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Chandra Bhatt:
The source of this code is Khalid Mughal : Chapter 9, Question 9:...

What exactly is the question?

Notice that the output is a sequence of 2-digit numbers, for example...

23
21
24
13
11
14
22
12

In each of these numbers, the first digit (1 or 2) indicates which method call we are seeing (corresponding to the passed int values, 10 and 20).

The second digit (1, 2, 3, or 4) indicates the execution point of the code. In particular, 1 and 2 indicate "before" and "after" the call to join. Note that 2 also indicates the run method is about to return. 3 and 4 indicate "before" and "after" the call to start another thread. Note that 4 also indicates the createThread method is about to return.

When an executing thread joins another thread, it waits for that other thread to die.

So the thing to consider is what happens between output of 21 (immediately before the call to join) and 22 (immediately after the call to join). And similarly, between output of 11 and 12.


"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer
sscce.org
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Thanks marc,

Actually I entangled in join() method call.
Now the things are quite clear.

Thanks and Regards,
cmbhatt
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Chandra,

I ran your program in XP JVM,
Here is the output i got
23
24
13
14
21
22
11
12
How it went like that:


1)First the nested function call occurs:

createThread(20,main)
1.1 printing 23
1.2 putting t2(20,main) in runnable queue.
1.3 printing 24
1.4 returning t2(20,main) Thread Object.

2)Second time outer funcion call occurs:

createThread(10,t2(20,main))
2.1 printing 13
2.2 putting t2(10, t2(20,main)) in runnable queue.
2.3 printing 14
2.4 returning t2(10, t2(20,main)) Thread Object.

3)Now JVM has to pick up a runnable thread. This process depends upon the
Scheduler(JVM).

3.1 its picked the first waiting thread t2(20,main)
3.2 printing 21
3.3 executing main.join() ***Here i got doubt like: why the program not breaking here, bec'ze if t2 waits for completion of main thread ***
3.4 printing 22

4)Second Thread t2(10, t2(20,main)) picked up

4.1 printing 11
4.2 t2(20,main).join as it has finished its job in step 3 no issues
4.3 printing 12

Thats the story.
I would like to know, doubt in 3.3.

If the Parent thread(main) complete its job, can the child threads in it still run ?

Please clarify the doubt.
I will give a mug of cheers.


Thanks & Regards, T.Srinivasan
SCWCD 1.4(89%), SCJP 5.0(75%)
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi,

Somebody please help me out !
My interpretation gone wrong any where ?
:roll:
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Marc Weber,

For the output you have displayed, I got a doubt

23
21 ---> main.join() [this -->t2(20,main)]

24
13
11 ---> t2(20,main).join() [this ---> t2(10,t2(20,main))]
--------
Here i am struck.
Actually t2(20,main) has not finished its "main().join()".

Please respond to me. My brain caught up heat. I want to mould my ideas into good shape when it is on heat"
swarna dasa
Ranch Hand

Joined: Mar 15, 2007
Posts: 108
The moment 14 is printed main thread completes its execution.

I am not able to understand your doubt but hope this helps.

Here is what each thread prints (using same sequence as Marc)




EDIT by mw: Added Code Tags to keep spaces intact.
[ March 28, 2007: Message edited by: marc weber ]
swarna dasa
Ranch Hand

Joined: Mar 15, 2007
Posts: 108
seems like the spaces were removed
reprinting the output in horizontal direction

Here is what each thread prints
Main thread - Normal e.g. 23
t2(20,main) - Bold e.g. 21
t2(10,t2(20,main)) - Bold & Italics e.g. 11


23 21 24 13 11 14 (Main Exits) 22 12



Basically 22 is printed after 14 (which indicates 22 is printed after main exits so t2(20,main) printed after main completed)

And 12 is printed after 22 which indicates t2(10,t2(20,main)) printed after t2(20,main) completed

[ March 28, 2007: Message edited by: swarna dasa ]
[ March 28, 2007: Message edited by: swarna dasa ]
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Interesting. I tried this code on a Windows XP machine today, and consistently got the same output as Srinivasan...

23
24
13
14
21
22
11
12

Unfortunately, this doesn't really illustrate the behavior of join. But Macs love multithreading. When I run this on a Mac, I consistently get the results I posted last night...

23
21
24
13
11
14
22
12

Again, what's interesting is what happens between 21 and 22. After 21 is output, the join method is called. So at this point -- as swarna described -- 22 cannot be output until after 14 is output, indicating that the main thread has died.

If we modify this code to give each thread a name, and announce that name with each println, we can see that swarna's analysis is correct.

OUTPUT from Mac...
23: main
21: t2.20
24: main
13: main
11: t2.10
14: main
22: t2.20
12: t2.10

Comparing this to XP output, we can also see how the threads were allowed to run on different platforms.

OUTPUT from XP...
23: main
24: main
13: main
14: main
21: t2.20
22: t2.20
11: t2.10
12: t2.10

Note: If you want to experiment with this, you can try to get the XP platform to mix these threads up a little better (for a more "simultaneous" execution) by inserting short calls to Thread.sleep at critical points. That way, while one thread is taking time to sleep, it's more likely that a different thread will be given a chance to run.
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Srinivasan thoyyeti:
...If the Parent thread(main) complete its job, can the child threads in it still run? ...

Absolutely! Each thread is its own entity -- kind of like a "mini program."

The main thread is the thread in which the Java program's main method executes. In this example, the main thread happened to create 2 other threads and call start on them. Once these other threads are started, the Java program will continue to run even after the main thread is finished. (If these other threads were daemons, then the program could end before the daemon threads finish. There's something else to experiment with!)
[ March 30, 2007: Message edited by: marc weber ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Swarna & Marc,

Thanks for digging into code.
By Marc: I now understood that if Parent thread dies Child threads may execute.

But both Swarna,Marc skipped "my point":

23
First Thread t2(20,main) starts executing...
21
main.join() --> forces to complete main that will produce fallowing
24
13
11
Upto here i got it. What happens when t2(20,main).join() executes

bec'ze t2(20,main) while executing main.join() and it got a call to join it self, like t2(20,main).join().

Please let me know what decision it will take...
(I know main completes by printing 14.)
[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
swarna dasa
Ranch Hand

Joined: Mar 15, 2007
Posts: 108
Are you stuck at the join call?

Lets see if this helps,



Srinivasan, hope i have at least scratched the surface of the doubt.
Thanks Marc, for the code tip

[ March 29, 2007: Message edited by: swarna dasa ]
[ March 29, 2007: Message edited by: swarna dasa ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Swarna,

Thank you. I understood now.
Do you know UML, The above diagram remembers me the Sequence diagram. Well done. You present things very well.

Still one doubt... reg Mac multi threading.

In Mac: Is it like the main waits until the thread started by it ends or calls join on it(main).
why bec'ze main started two thread's t2(10,main). t2(10,t2(20,main))
and main came into picture, when thread pushed it to run.
Does it really need EMF(electro motive force ) from child threads.

main process
1)after 23
main started t2(20,main) and again came to picture by main.join()


2)after 13
main started t2(10,t2(20.main)) and again came to picture by t2(20,main).join() [ indirect nod from t2(20,main) "Hey main() complete your job"]


Mac looks pre-emptive style. But i want to know how it does... like main completly stopped from executing and let child thread to run.

Does it assign any high priority to childs(more than 5).

Please let me know. I think we had a very good time...

------------------------------------------------------------------------
Windows behavior quiet clear to me. As we haven't mentioned any priority,
it gives all threads 5(Normal).
As it is Non pre-emptive style.
1) main started first
puts t2(20,main) into queue.
puts t2(10,t2(20,main)) into queue.
2) t2(20,main) runs main.join() already completed(no problems).
3) t2(10,t2(20,main)) runs t2(20,main).join() already completed(no problems)
-----------------------------------------------------------------------------
[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Marc Weber,

Where are you...???
Please answer my last doubt posted above.

I am executing wait on you....



Please notify me.

[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
boolean volatile No_Reply[] = {true , true, true, true};
String[] bartenders = { "Bert Bates", "Henry Wong", "Barry Gaunt","Marc Weber" };

for (byte i=0; i < bartenders.length ; i++){

synchronize(bartenders[i]){
if(No_Reply[i]){
S.o.p("I am longing for you: "+ bartenders[i]);
bartenders[i].wait(10000);
if ( i == bartenders.length -1) i = -1;
}
}

}

[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Srinivasan thoyyeti:
Hi Marc Weber,

Where are you...???
Please answer my last doubt posted above...

Hey, I need to call Thread.sleep(x) occasionally!

As far as I know, Windows and Mac both use preemptive multitasking now. (Prior to 95 and NT, Windows used "cooperative multitasking," as did Macs prior to OS X. Ref: Wikipedia - Computer Multitasking.)

Basically, the Mac's thread scheduler just seems more prone to slicing time between different threads. In other words, it switches between threads more frequently for more of a "parallel" or "simultaneous" effect. I have no idea what the underlying (platform-dependent) algorithms might be.

(I think Henry Wong is the thread expert here.)
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Hi Srini,

I see, you have been waiting for "Marc Weber" and then all the four bartenders, if I notify you it wont do for you. Keep waiting and I am also hoping to execute after you get notified.





Thanks and Regards,
cmbhatt
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Chandra Bhatt:
... I see, you have been waiting for "Marc Weber"...

Well, Java is case sensitive...
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi marc weber,

Things with windows are very clear and understandable.

CASE: NO PRIORITY SET
// Windows OS when no priority set gives all 5(Normal) priority.
// Main ran un-interuptedly. Childs time sliced due to join().

C:\Srinivasan\MyWork>java Joining
23
24
13
21
This : Thread(20 , main)
main.join()
14
22
11
This : Thread(10 , Thread(20 , main))
Thread(20 , main).join()
12

CASE: When priority set for childs
t2.setPriority(10);
t2.start();

// Main pre-empted, due to high priority childs.
// Here is the Output
C:\Srinivasan\MyWork>javac Joining.java

C:\Srinivasan\MyWork>java Joining
23
21
This : Thread(20 , main)
main.join()
24
13
11
This : Thread(10 , Thread(20 , main))
Thread(20 , main).join()
14
22
12
Having said about Windows;

Does any in the world tell me about the program behavior in MAC???
1. "What implicit prority Mac assigns in general to child threads"
2. Is it the implicit priority (or) scheduler's switching between thread happend.


I can wait on "MAC WORLD OF JAVA PROGRAMMERS".
[ March 29, 2007: Message edited by: Srinivasan thoyyeti ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi Chandra,

My intention is to know for once

1."How Mac System gives priority to newly allocated child"
2.if priority kept common then Is it the Mac scheduler switches threads to time slice.

I have wait() on bartenders bec'ze they might have seen different environments.

Sorry yaar. It seems i hurt you.
[ March 30, 2007: Message edited by: Srinivasan thoyyeti ]
Chandra Bhatt
Ranch Hand

Joined: Feb 28, 2007
Posts: 1707
Hi Srini,

No Srini, Nothing like what you feel. Actually I want to know the result of the code execution on the Mac environment not available with me. The discussion went quite interesting. I hope any of the bartender will focus on this issue. But as far as XP, it gives constant result what has already been mentioned there.

Enjoy madi,

Thanks and Regards,
cmbhatt
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Srinivasan stated, "Things with Windows are very clear and understandable... Windows OS when no priority set gives all 5 (Normal) priority. Main ran un-interrupted."

But if all threads have the same priority, then why should main be allowed to hoard the CPU? The whole idea of multithreading is to give the appearance that multiple things are happening simultaneously -- which is why we use the word "concurrency." As explained by Eckel in Thinking in Java...
With threads, the CPU will pop around and give each thread some of its time. Each thread has the consciousness of constantly having the CPU to itself, but the CPU�s time is actually sliced between all the threads.

So it's the job of the platform-dependent thread scheduler to let multiple threads share the CPU. In this example, the only apparent difference between the XP and Mac schedulers is that the Mac seems more willing to switch between threads, resulting in a "finer mix" of different threads. Isn't this exactly what we would expect from "concurrency"?

Again, I don't know the underlying algorithms used for thread scheduling (and that's certainly beyond the scope of the SCJP exam). But based on the results we've seen -- which might vary from one execution to the next -- here's a rough idea of what might be happening in this particular example...

Regardless of platform, the first line of output will always be 23, because there is only one thread running at that point. But immediately after this, start() is called on t2.20, and this is where we start to see differences.

The Mac scheduler says, "Hey, I see there's another thread that wants to run. My job is to divide CPU time so they can both do what they need to do, so let's give this new thread some time." The Mac scheduler allows thread t2.20 to output 21, then says, "Oh, I see that join has been called, telling me that t2.20 wants to wait until main has finished. Okay, let's give the CPU back to main." So main outputs 24, followed by 13. Immediately after this, start() is called on t2.10, and the Mac scheduler says, "Now there are three threads I'm trying to keep happy. But t2.20 wants to hold off until main dies, so let's give this new thread a chance." So t2.10 outputs 11, and the Mac scheduler says, "Now I see that join has been called again, this time telling me that t2.10 wants to wait until t2.20 has finished. So both t2.20 and t2.10 have done as much as they can for now. So I'll give main the CPU again." So main outputs 14, then dies. The Mac scheduler says, "Well, now that main has finished, I'm back to scheduling two threads. Let's see... t2.10 wants to wait for t2.20 to finish, so I'll give the CPU back to t2.20, which can run now that main has finished." So t2.20 outputs 22, then dies, and the Mac scheduler says, "Well, now t2.10 is the only thread left, and it can run because t2.20 has finished." So t2.10 outputs 12.

In contrast...

The XP scheduler says, "I see there's another thread that wants to run, but I'm going to continue running the current thread as if it's the only one." So instead of giving the new thread a chance to run, the XP scheduler allows the main thread to continue, outputting 24, followed by 13. Then the XP scheduler says, "I now see a third thread that wants to run, but I'm going to continue to let the main thread dominate the CPU (even though it has the same priority)." So main outputs 14, and dies. The XP scheduler says, "Well, now I have no choice but to let one of the other threads run." So t2.20 is given CPU time to output 21, and the XP scheduler says, "Oh, I see that join has been called, telling me that t2.20 wants to wait until main has finished. Uh... Well, this really has no effect, because I never split main's time, so it's already died. I see that t2.10 still wants a chance to run, but I'll let t2.20 continue instead (even though it has the same priority)." So t2.20 outputs 22, then dies. And the XP scheduler says, "There's only one thread left, so..." t2.10 outputs 11, and the XP scheduler says, "Oh, I see that join has been called again, this time telling me that t2.10 wants to wait until t2.20 has finished. Uh... Well, this really has no effect, because I never split t2.20's time, so it's already died." So t2.10 outputs 12.

Note: After running this several more times on XP, I've finally seen different output that appears to show some effect of join...

23: main
24: main
13: main
21: t2.20 (join called)
14: main
22: t2.20
11: t2.10
12: t2.10

But in the Mac output, I see more effective concurrency and a better illustration of join's effect on this code.

I hope that helps.
megha joshi
Ranch Hand

Joined: Feb 20, 2007
Posts: 206
Hi all,

I noticed something which I never noticed before, forgive me if I am being stupid...

For the anonymous classes the constructor doesnt run when it encounters line
Thread t = new Thread{...};
Its runs only when the instance variable t is used first time.
For non anonymouns classes, the construtor runs as soon as it encounters the line
MyThread t = new MyThread();
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by megha joshi:
...For the anonymous classes the constructor doesnt run when it encounters line
Thread t = new Thread{...};
Its runs only when the instance variable t is used first time.
For non anonymouns classes, the construtor runs as soon as it encounters the line
MyThread t = new MyThread();

Are you confusing the run() method with the constructor? The run() method will not execute until after start is called (or unless run is called directly in an existing thread). But the constructor should execute when "new" is used.

It might help to see this if you extend Thread with a constructor that announces itself. For example...

...and then use Threader t2 = new Threader() {...};.
[ March 30, 2007: Message edited by: marc weber ]
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi marc,

Thanks marc for that long explanation.

I understand Mac loves all threads with same priority and time slices.
But Windows XP preference is given to Parent thread, though child eagerly waiting for run().



You have talked about the one side , where Windows is weak in time slicing.

Lets talk about the other side,

---> Windows understands thread priorities.
If we give child a high priority(*10). it shows the same Mac output(with out any priority set in Mac).

---> My Doubt: Does Mac really respects priority of thread.
I want to test above scenario, by giving the child less priority(1).
And now wants to see whether "it really considers priority (or) time slicing" *** DEPENDING ON THE RESULT I WILL CHANGE MY OS ***

I DON'T HAVE A MAC MACHINE, SOMEBODY PLEASE GIVE ME OUTPUT FOR MY TEST CASE
megha joshi
Ranch Hand

Joined: Feb 20, 2007
Posts: 206
Thanks Marc,

That rectifies my concepts...I misunderstood run() for constructor()...didnt look carefully... Thanks.
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

I'm not sure why the question of thread priority comes up -- especially in the context of this example, where each thread has the same priority. My understanding is that assigning numeric priorities to Java threads is often futile, since there are no guarantees of how this will be implemented on different platforms. In fact, attempting this can create problems. As Horstmann and Cornell warn on page 19 of Core Java 2: Volume II -- Advanced Features...
...thread priorities are highly system dependent...

For example, Windows NT/XP has seven priority levels. Some of the Java priorities will map to the same operating system level. In the Sun JVM for Linux, thread priorities are ignored altogether -- all threads have the same priority.

Thus, it is best to treat thread priorities only as hints to the scheduler. You should never structure your programs so that their correct functioning depends on priority levels.

CAUTION: ...If you have several thread with a high priority that rarely block, the lower-priority thread may never execute.

I think I took these words (or something like them) to heart long ago, and made a mental note to avoid using thread priorities.

In Thinking in Java, Eckel says...
...Windows 2000 has 7 priority levels that are not fixed, so the mapping is indeterminate (although Sun's Solaris has 2^31 levels). The only portable approach is to stick to MAX_PRIORITY, NORM_PRIORITY, and MIN_PRIORITY when you�re adjusting priority levels.

With this in mind, I adjusted the code to use different thread priorities. For convenience, I also added a static method to help output the thread name and priority. I tried two approaches: first setting t2 to a lower priority, and then setting main to a higher priority.

I ran these numerous times and almost always matched Windows' output for equal-priority threads. That is...

Mac output, setting t2 to MIN_PRIORITY:
23: main: priority 5
24: main: priority 5
13: main: priority 5
14: main: priority 5
21: t2.20: priority 1
22: t2.20: priority 1
11: t2.10: priority 1
12: t2.10: priority 1

Mac output, setting main thread to MAX_PRIORITY, and t2 to NORM_PRIORITY:
23: main: priority 10
24: main: priority 10
13: main: priority 10
14: main: priority 10
21: t2.20: priority 5
22: t2.20: priority 5
11: t2.10: priority 5
12: t2.10: priority 5

I say "almost always" because every once in a while, when start was called on a new thread with lower priority, that thread would be given a brief opportunity to run.
23: main: priority 5
21: t2.20: priority 1
24: main: priority 5
13: main: priority 5
11: t2.10: priority 1
14: main: priority 5
22: t2.20: priority 1
12: t2.10: priority 1

However, this rare behavior seemed to disappear entirely when I set main to MAX_PRIORITY and t2 to MIN_PRIORITY.

So I guess I would summarize by saying: When threads are of equal priority, the Mac scheduler appears eager to time slice, sharing the CPU by frequently switching between threads. But the Mac scheduler also takes thread priorities into consideration, and will not switch as frequently if higher priority threads are running. In contrast, the XP scheduler seems reluctant to time slice unless a waiting thread has a higher priority.
Srinivasan thoyyeti
Ranch Hand

Joined: Feb 15, 2007
Posts: 557
Hi marc,

Thanks a lot marc. Thats all I need.
I promise i am not going to depend upon JVM or OS for time slicing or prioritaise some threads to hold on running state.

Just experimented with threads to know hows. I am satisfied with our discussion.
 
Consider Paul's rocket mass heater.
 
subject: Joining Thread, Explanation required
 
Similar Threads
Threads:Pls. Help
Thread doubt please help
Joining threads
A hard question
Help Required with this code on threads