Bayare Deepak Singh
Bayare Deepak Singh

Reputation: 66

What mistake i have done in my debugging java multi-threading?

class TestJoinMethod3 extends Thread{  
  public void run(){  
   System.out.println("running...");  
  }  
 public static void main(String args[]){  
  TestJoinMethod3 t1=new TestJoinMethod3();  
  TestJoinMethod3 t2=new TestJoinMethod3();  
  System.out.println("Name of t1:"+t1.getName());  
  System.out.println("Name of t2:"+t2.getName());  
  System.out.println("id of t1:"+t1.getId());  
  
  t1.start();  
  t2.start();  
  
  t1.setName("Hello");  
  System.out.println("After changing name of t1:"+t1.getName());  
 }  
}

i got this out put

Output:
Name of t1:Thread-0
Name of t2:Thread-1
id of t1:8
running...
After changling name of t1:Hello
running...

but according to my debugging i expected this one

Output:
Name of t1:Thread-0
Name of t2:Thread-1
id of t1:8
running...
running...
After changling name of t1:Hello

What mistake i have done in my debugging?

Upvotes: 0

Views: 86

Answers (2)

Stefan
Stefan

Reputation: 3

Threads run independently, you need to synchronize them to get the desired output. What you can do is:

class TestJoinMethod3 extends Thread{
public void run(){
    System.out.println("running...");
}
public static void main(String args[]){
    TestJoinMethod3 t1=new TestJoinMethod3();
    TestJoinMethod3 t2=new TestJoinMethod3();
    System.out.println("Name of t1:"+t1.getName());
    System.out.println("Name of t2:"+t2.getName());
    System.out.println("id of t1:"+t1.getId());

    t1.start();
    t2.start();

    try{
        t1.join();
        t2.join();
    }catch(InterruptedException e){
        System.out.println("Interrupted");
    }

    t1.setName("Hello");
    System.out.println("After changing name of t1:"+t1.getName());
}

}

Upvotes: 0

Arkantos
Arkantos

Reputation: 6608

As mentioned here, Threads are meant for executing code/instructions separately and usually up-to the mercy of Scheduler, an Operating System component.

When you say t1.start(), you're asking for a new thread to be started, but it's not guaranteed to run immediately. It goes in to a state called Runnable which makes them eligible for scheduling. Once the Scheduler picks these Runnable threads and allocates CPU to them, then they're actually in Running state. This is actually the time when your code inside run() is executed.

In java, your main thread (in your case the thread executing your main()) will not wait until all the threads it spawned are done executing their code. All threads are usually executed in a call-stack separate from your main method call-stack so the control immediately comes back to main() for executing the remaining the code (in your case , sys-outs). It's possible that by the time, main() ended, Thread t2 is not picked by the Scheduler, that's why you're not seeing 2 Running statements. Perhaps, if you try several times, then you might 2 statements but it's not guaranteed. Like I said earlier, it's up to the scheduler.

Perhaps, if you try to write them to a file, then you might see 2 Running statements (or) you can try using a thread-pool from Executors class which will not shutdown until you explicitly call shutdown(). That another way to experiment with threads without having to create them by ourselves.

Here's an image to help you understand the flow. Every method call becomes a new stack frame (even calls to constructors but I removed them for brevity) in a call-stack executed by a thread. As and when a method is completed, stack frames are removed and finally comes back to main().

Contains visuals for how threads are executed in separated stacks

PS: Above image is an approximation, it's not an accurate representation of how JVM manages threads.

To make the main thread wait for the threads to run to completion, you can use a lot of thread co-ordination constructs like join(), wait() & notify(), Semaphores & Cyclic Barriers.

join() is the simplest of all but it doesn't scale well when you're dealing with lot of threads.

So if you want your main thread to wait until t1 and t2 are done, you need to explicitly say so by doing something like this

t1.join() // blocks the main method thread until t1 is done
t2.join() // block the main method thread until t2 is done

If you're using join(), then you need to handle InterruptedException. join() also has overloaded method that waits for a specific time instead of waiting indefinitely like the no-arg version.

Upvotes: 2

Related Questions