aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes join() method; guarenteed behaviour Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "join() method; guarenteed behaviour" Watch "join() method; guarenteed behaviour" New topic
Author

join() method; guarenteed behaviour

Ram Manoj
Ranch Hand

Joined: Jan 12, 2008
Posts: 52
From K&B book.
When one thread calls the join() method of another thread, the currently
running thread will wait until the thread it joins with has completed.

Here is a sample program, I coded to understand join() method.
Here t.join() is invoked from the main method. The 'main' Thread will wait till thread 't' has completed.
Here do I modify the code, if I want the threads 't','t2','t3' be executed one followed by the other irrespective of 'main' Thread. Output:0 0 0 before join
1 1 1 2 2 2 end of main
Karl Prenton
Ranch Hand

Joined: Mar 10, 2008
Posts: 51
I'm not sure if you can!
You can synch the run method such that it won't get interrupted but that doesn't guarantee the order of threads started, you specified t then t2 then t3.
Remember that the output you gave is not guaranteed - try running it several times...
[ June 05, 2008: Message edited by: Frank Zito ]
Ram Manoj
Ranch Hand

Joined: Jan 12, 2008
Posts: 52
Hi Frank,

I think there is confusion here.

What I want is 't2' thread join 't' and 't3' thread join 't2'.

So for this how do i modify my code!
Karl Prenton
Ranch Hand

Joined: Mar 10, 2008
Posts: 51
does this help (modifies main method though) ?

Ram Reddy
Ranch Hand

Joined: Feb 20, 2007
Posts: 88
hi manoj,

I hope i understood your requirement.
Please find two programs below.

Program 1 :- is like your requirement

program 2:- to execute threads one by one . I think this is not a good approach.

program 1:-


class Test12 extends Thread
{
Thread threadObj = null;
public Test12() {}
public Test12(Thread thread)
{
this.threadObj = thread;
}
public static void main(String...strings)
{
Test12 t = new Test12();
Test12 t2 = new Test12(t);
Test12 t3 = new Test12(t2);
t.start();
t2.start();
t3.start();
System.out.println("before join");
try
{
t.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("end of main");
}
public void run()
{
System.out.println("Run Method of " + Thread.currentThread().getName());
try
{
if(threadObj != null)
{
threadObj.join();
}
for(int i=0;i<3;i++)
{
System.out.print(i+" ");
sleep(100);
}
System.out.println("End of Thread " + Thread.currentThread().getName());
}
catch(InterruptedException e)
{
System.out.println("Interrupted Exception");
}
}
}

program 2:-



class MainJoin
{
public static void main(String...strings) throws Exception
{
Join j1 = new Join();
Join j2 = new Join();
Join j3 = new Join();
j1.setName("Join Thread 1");
j2.setName("Join Thread 2");
j3.setName("Join Thread 3");
System.out.println("Before starting the thread J1");
j1.start();
System.out.println("Before joining the J1 Thread");
j1.join();
System.out.println("Before starting the thread J2");
j2.start();
System.out.println("Before joining the J2 Thread");
j2.join();
System.out.println("Before starting the thread J2");
j3.start();
System.out.println("Before joining the J3 Thread");
j3.join();
System.out.println("End of the main thread");
}
}

class Join extends Thread
{
public void run()
{
System.out.println("Start of the thread " + Thread.currentThread().getName());
for(int i = 0; i < 10; i++)
{
System.out.println(" I value is " + i);
}
System.out.println("End of the Thread : " + Thread.currentThread().getName());
}
}

Can any one tell me is the second program is a good approach?
If not how to write it another way?

Rami.
Mustafa Musaji
Ranch Hand

Joined: May 03, 2008
Posts: 52
I really don't understand how join() works. If join() comes after you have started the threads (which are now for arguments sake are running), when the main hits the join() call for that thread... its a little bit too late as they threads have already started.

As an example, here some code I wrote, wanting the output to be along the lines of a thread starts, that thread finishes before another one starts and finishes and then the last one starts and finishes. This is what I understand the join() method to do.



What I find is that join() is being called AFTER the threads have all completed!

Actual Output:
one started
three started
two started
one finished
three finished
two finished

Desired Output:
one started
one finished
two started
two finished
three started
three finished


I am 100% sure I am missing some fundamental rule and would appreciate your help.
[ June 06, 2008: Message edited by: Mustafa Musaji ]

SCJP 5.0 - Passed
robert stannard
Ranch Hand

Joined: Jun 02, 2008
Posts: 37
Hi Mustafa,

to get the output your requiring, I think you need to add the "synchronize" keyword to your "run" method. This I think forces only one thread to access the method at a time. I tried it with your example and it worked for me, although I had to increase your variables quite alot to slow my machine down!!

I hope this helps.

Robert.


SCJP 1.5
Mustafa Musaji
Ranch Hand

Joined: May 03, 2008
Posts: 52
Hi Robert,

I agree with you, using synchronize does work, but then there would be no need for the join() method as each thread would access the run method seperately anyway right?

I guess what I am trying to say is I don't quite understand how the join() method is used correctly. When I see it in a mock I just seem to get confused as to what the code will do.

Should I just hope I don't get too many Thread questions in my SCJP Exam!!!
robert stannard
Ranch Hand

Joined: Jun 02, 2008
Posts: 37
Hi Mustafa,

I may have given you a "bum steer" in my previous post. I think you need to add a "synchronized" block to the code and lock on an external Object like "System.out" to lock that bit of code from other Threads. I made this small change to your code,


which then gives me the Ouput,
One Started
One Finished
Three Started
Three Finished
Two Started
Two Finished

I dont think its possible to tell the scheduler which thread to run next - thats why you have thread "Three" running before thread "Two" - but as you can see from the output, once a thread is in your "Run" method, no other thread can access the code until its finished.

I hope this helps.
robert stannard
Ranch Hand

Joined: Jun 02, 2008
Posts: 37
I think the problem with your Join is that you are joining to the Main thread and not joining one thread to another, so what happens is that the Main thread runs and completes and then the other threads run on after the other in not particular order.

I also struggle with Thread questions and am hoping that I dont have too many difficult ones !
Mustafa Musaji
Ranch Hand

Joined: May 03, 2008
Posts: 52
Forgot to say that to use synchronize you would have also have create one "GoingRunning" object and three Thread objects using the same "GoingRunning". Synchronize would only work on the same object.

Basically it would mean I could not create three different objects of GoingRunning and have them access the run() method one after the other using synchronize. I could use synchronized(GoingRunning.class)....

.... anyway, my point is I don't understand join()!!!
Mustafa Musaji
Ranch Hand

Joined: May 03, 2008
Posts: 52
Originally posted by robert stannard:
I think the problem with your Join is that you are joining to the Main thread and not joining one thread to another, so what happens is that the Main thread runs and completes and then the other threads run on after the other in not particular order.

I also struggle with Thread questions and am hoping that I dont have too many difficult ones !


This sort of makes sense, but then where would I put the code to join the threads?
robert stannard
Ranch Hand

Joined: Jun 02, 2008
Posts: 37
I don't think you can do that - not from within the Main() method anyway.

I think what I said before about the Join was actually the wrong way around. The way you've coded the Join, "gr1.join()" you're saying join (or run) the Main() thread to the end of this thread gr1 (or gr2 or gr3).
You can observe this effect but making the following small change to your code. Try un-commenting and re-commenting the block and see where the System.out prints. You will see that when the block is commented out the print statement appears at the top of the output and when you uncomment the block it prints at the bottom of the output, showing that the Join statement has kicked in and is stopping the Main() thread from continuing until the other threads have completed.

I dont think you can daisy-chain Joins together like you're trying to do - not in the Main() method anyway.



[ June 06, 2008: Message edited by: robert stannard ]
[ June 06, 2008: Message edited by: robert stannard ]
Mustafa Musaji
Ranch Hand

Joined: May 03, 2008
Posts: 52
Ah yeah I get it. That does make sense. I was making the mistake of thinking that calling gr1.join() was asking that thread to join on the main, but its asking the current thread you're running, in this case "main" to join on gr1 when it has finished.

Is that right?
robert stannard
Ranch Hand

Joined: Jun 02, 2008
Posts: 37
Yes thats exactly right. Its a bit confusing I know.

I dont know how you would daisy-chain gr1 to gr2 to gr3 to build up dependancies there, I dont think it can be done. I think thats what "synchronized" is good for.

I hope that helps.
Ram Manoj
Ranch Hand

Joined: Jan 12, 2008
Posts: 52
Thanks Robert, Mustafa and Reddy in taking this discussion further.

Hi Frank,

Originally posted by Frank Zito:
does this help (modifies main method though) ?


It works wonderfully. And the use of synchronized for ordering is brilliant.
But here the join() method does little.Even if we comment out join() methods, the threads are synchronized and seemingly join each other, but then I suppose the order is not guarenteed.

I have modified my code so it can accomodate multiple threads in an ordered way.


But then how do we accomplish the same task using join() method instead of using synchronized block code?

Ranchers please put in your views.
Karl Prenton
Ranch Hand

Joined: Mar 10, 2008
Posts: 51
Ram Reddy is correct in suggesting that the join should be in the run method in order to control the order (doh!). The synch only prevents the block from being interrupted (by a similar thread).
Joining the main thread is not the issue, if I understand the problem correctly.
venkatesh badrinathan
Ranch Hand

Joined: Aug 03, 2008
Posts: 77
can anyone please give me a simple example to daisy chain threads?? although i have read threads in detail, i still have some issues writing join() and sychronized methods in program... is there any source where i could get details about join() and synchronized()...???


SCJP1.5
Saurabh Vyas
Ranch Hand

Joined: Sep 02, 2003
Posts: 72
Hi Guys,

Try this example written by me.

I guess it solves your problem of Running 3 Thread T1, T2, T3 along with main Thread with a condition that T1 should finish first, T2 should finish Second and T3 should finish 3rd and main should finish last. It makes use of join() to accomplish the task.



Cheers !!
Saurabh
Sumit Bisht
Ranch Hand

Joined: Jul 02, 2008
Posts: 329

Guide me why the foll code does compile(it even runs correctly at runtime and ends up throwing a out of memory exception)

 
It is sorta covered in the JavaRanch Style Guide.
 
subject: join() method; guarenteed behaviour