Friday, 5 May 2017

12. join() drawbacks


1. How join() will break the application functionality.
  1. join() is a synchronized method, so current thread needs object lock of specified thread object.
    t2.join() → this line is executed by a thread t1
  2. In above example t1 thread needs t2 object lock for entering into join() of t2 object.
Case 1 : If t2 object lock is not available
  • t1 thread calling t2.join(), join() is synchronized method so t1 thread needs t2 object lock to execute t2.join()
  • If may be another thread like t3 may holds t2 object lock and executing user defined synchronized methods of t2 object.
  • Suppose if t3 thread completed execution of synchronized method of t2 object in 1min, then t1 thread need to wait 1 min for executing t2.join()

public class ThreadDemo extends Thread {

Thread mainThread;

@Override
public  void run() {

try {
Thread.sleep(2000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main thread state is = " + mainThread.getState());
System.out.println("completed t1 thread");

}

public static void main(String[] args) throws InterruptedException {

ThreadDemo t1 = new ThreadDemo();
t1.mainThread = Thread.currentThread();
t1.start();
ThreadDemo2 t2 = new ThreadDemo2();
t2.t1 = t1;
t2.start();

Thread.sleep(100l);
System.out.println("main thrad calling join()");
t1.join();
System.out.println("i am out of join");
}
}

class ThreadDemo2 extends Thread{
ThreadDemo t1 = null;
@Override
public void run() {
m();
}
public void m() {
synchronized (t1) {
System.out.println("i am t2 and executing inside m() by locking t1 object");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i am t2 and releasing the lock and end of m() of t2");
}

}
}

Output
i am t2 and executing inside m() by locking t1 object
main thrad calling join()
main thread state is = BLOCKED
completed t1 thread
i am t2 and releasing the lock and end of m() of t2
i am out of join → executes after 20 secs


Case 2 : If t1 completes then join() notify the all threads wait() on t1 will come to runnable state
  • t1 thread calling t2.join(), join() is synchronized method so t1 thread needs t2 object lock to execute t2.join()
  • Now t1 thread calls t2.wait() internally(join() logic), so t1 thread will go to waiting state and releases the lock of t2 object lock.
  • After releasing t2 object lock t1 thread will go to waiting state.
  • t1 thread will come back to runnable state in the below cases only
    • Any thread executes t1.interrupt()
    • Any thread executes t2.notifyAll() or t2.notify()
  • So JVM will execute t2.notifyAll() after completing t2 thread, then t1 thread will come back to Runnable state.
  • Suppose one more thread t3 is also executes t2.wait() (we wrote this logic explicitly) and waiting for t2 object lock in waiting state.
  • Now JVM will execute t2.notifyAll() after completing t2 thread, then t1, t3 both threads are coming out from waiting state.
  • So if you use t2.join() then don’t use t2.wait() in your coding part.
Case 3 : If we call explicitly notify() on t2 object then t1 will come to runnable state
  • t1 thread calling t2.join(), join() is synchronized method so t1 thread needs t2 object lock to execute t2.join()
  • Now t1 thread calls t2.wait() internally(join() logic), so t1 thread will go to waiting state and releases the lock of t2 object lock.
  • After releasing t2 object lock t1 thread will go to waiting state.
  • t1 thread will come back to runnable state in the below cases only
    • Any thread executes t1.interrupt()
    • Any thread executes t2.notifyAll() or t2.notify()
  • Before completing t1 thread, if we explicitly called t2.notifyAll() then t1 thread come back to Runnable state and executes while loop written inside of join()
    while(t2.isAlive()){
    t2.wait();
    }
  • T1 thread will come to runnable state and take the t2 object lock and executes while condition, it will returns true because t1 thread is still alive.
  • T2 thread go to inside loop once again and executes t2.wait()
  • It again goes to waiting state until t1 thread dead only it will come out of while loop only.
  • In above case we can bring the thread t1 from waiting state to runnable state, but not from join() to our application before t2 deads.

public class ThreadDemo extends Thread {

Thread mainThread;

@Override
public  void run() {

while (true) {
try {
Thread.sleep(100);
m();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main thread state is = " + mainThread.getState());
}

}

public synchronized void m() {

this.notifyAll();

}

public static void main(String[] args) throws InterruptedException {

ThreadDemo t1 = new ThreadDemo();
t1.mainThread = Thread.currentThread();
t1.start();

t1.join();
System.out.println("i am out of join");
}
}
main thread state is = WAITING
main thread state is = BLOCKED
main thread state is = WAITING
main thread state is = WAITING
main thread state is = BLOCKED
main thread state is = BLOCKED
main thread state is = RUNNABLE
main thread state is = BLOCKED
main thread state is = BLOCKED
main thread state is = BLOCKED
main thread state is = BLOCKED
main thread state is = WAITING
……..





No comments:

Post a Comment

3. Java Program to create Binary Tree