1

I am trying to follow this example in order to understand the join() method:

class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo(String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { synchronized(PD) { PD.printCount(); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo("Thread - 1 ", PD); ThreadDemo T2 = new ThreadDemo("Thread - 2 ", PD); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); } catch (Exception e) { System.out.println("Interrupted"); } } } 

I understood that T1.join() for example makes the main thread wait for T1 to finish in order to continue with its flow. Am I correct here?

So, I modified the code like this:

 System.out.println("1"); T1.start(); System.out.println("2"); T2.start(); // wait for threads to end try { System.out.println("3"); T1.join(); System.out.println("4"); T2.join(); System.out.println("5"); } catch (Exception e) { System.out.println("Interrupted"); } 

in order to try and follow the complete flow.

And this is what I get every time:

1 Starting Thread - 1 2 Starting Thread - 2 3 4 5 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting. 

and I cannot explain it...

How come the counter prints were printed after the "5" character??? I probably don't understand well the join issue...

8
  • @Zoe You don't seem to know what Thread.join() does, you may want to refrain from posting such comments as they only lead to confusion. Commented Feb 6, 2018 at 13:27
  • 3
    I just took a peek at the code in that tutorial, and it is confusingly bad by starting new threads from a thread start. I strongly suggest you stop using that site, it seems to be rubbish. Commented Feb 6, 2018 at 13:31
  • 3
    @MarkRotteveel Could not agree more. If the goal is to teach synchronization, you don't need threads spawning threads to demonstrate that. If the goal is to demonstrate that waiting for a thread to die does not necessitate waiting for it's children to die, the synchronization guff just gets in the way. Commented Feb 6, 2018 at 13:33
  • 1
    Yes, you should include the code in your question: questions must be self-contained. Commented Feb 6, 2018 at 13:39
  • 2
    I second @MarkRotteveel: overriding Thread.run() is moderately iffy, overriding Thread.start() is a massive no-no, and then to start another thread from it is a Very Bad Idea™. I'd use the official Oracle tutorials, which aren't perfect but aren't this bad. Commented Feb 6, 2018 at 13:45

3 Answers 3

6

You start a thread (A) which starts another thread (B).

You wait for thread A to finish - which is almost immediate as it barely does anything besides kick off thread B - but thread B is still running independently.

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

Comments

2

As @Micheal said, your main thread are not joinning to "desire" thread, perhaps this code can help you to clarify. It helps Main thread to join with the inside threads.

class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo(String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { synchronized(PD) { PD.printCount(); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } public void joinInsideThread() throws InterruptedException { if (t != null){ t.join(); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo("Thread - 1 ", PD); ThreadDemo T2 = new ThreadDemo("Thread - 2 ", PD); System.out.println("1"); T1.start(); System.out.println("2"); T2.start(); // wait for threads to end try { System.out.println("3"); T1.joinInsideThread(); System.out.println("4"); T2.joinInsideThread(); System.out.println("5"); } catch (Exception e) { System.out.println("Interrupted"); } } } 

2 Comments

@dushkin I have tried to keep the essence of your example, but keep in mind that it is a poorly designed example for the purpose of teaching thread synchronization.
@dushkin Please, read carefully the Michael and Mark Rotteveel comments. I agree with them.
1

I am trying ... to understand the join() method

t.join() is trivially easy to understand. All it does is wait for thread t to die. It doesn't do anything else. Most especially, it does not do anything to thread t.

A call to t.join() will do nothing, and return immediately if t has already finished. Otherwise it will do nothing, and it will not return until t is finished.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.