Friday, 7 February 2020

What is Thread Join in Java with Example

Let’s us briefly discuss about Thread.

Thread is basically a lightweight sub-process, a smallest unit of processing and Multithreading in java is a process of executing multiple threads simultaneously.

In other words, executing several tasks simultaneously where each task is a separate independent part of the same program is called Thread based multitasking and each independent part is called as a Thread.


Using Thread class join() method, we can prevent a Thread from execution.

join() method:

If a thread wants to wait until completing of some other thread, then we should go for join() method.
For ex: If a thread “T1” wants to wait until completing of “T2” thread, then thread “T1” has to call T2.join() . If thread “T1” executes T2.join() method, then immediately “T1” thread will enter into waiting state until “T2” thread completes its execution. Once “T2” thread completes its execution, then “T1” thread can continue its execution.


Let us take an another simple example on Software development to understand Thread join() method.



Let us understand the above table.

In this above table, Step-1(Planning & Requirement Analysis), Step-2(Design the Product Architecture) and  Step-3(Development and Test the product) phases are assigned T1, T2, and T3 as thread respectively. So Step-2(T2) thread has to wait until Step-1(T1) completes its execution. Hence “T2” thread has to call T1.join() method.

Similarly,  Step-3 (T3) thread has to wait until completion of Step-2(T2) thread. Hence “T3” thread has to call T2.join().

Methods

  1. Public final void join() throws InterruptedException
  2. Public final void join(Long milliSeconds)  throws InterruptedException
  3. Public final void join(Long milliseconds, int nanoseconds)  throws InterruptedException

Note:

Every join() method throws InterruptedException which is a checked exception. Hence it is compulsory to handle  this exception either by using try/catch block or by using throws keyword. Otherwise you will get compile time error.

Let’s come to some cases with  examples:  

Case - 1:  Waiting of main thread until completing of child thread.

class MyThread extends Thread  {
    public void run() {
        for(int i=0; i<5; i++) {
            System.out.println("Child Thread Running");
            try {
                Thread.sleep(2000);
            }
            catch(InterruptedException exp) {
                exp.printStackTrace();
            }
        }
    }
}

public class ThreadJoinChild {
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        t.start();
        t.join();
        for(int j=0; j<5; j++) {
            System.out.println("Main Thread Running");
        }
    }
}

o/p:

Child Thread Running
Child Thread Running
Child Thread Running
Child Thread Running
Child Thread Running
Main Thread Running
Main Thread Running
Main Thread Running
Main Thread Running
Main Thread Running



Notes:
  • So, the output of this above program shows, child thread is running first and once it completes its execution,the parent/main thread starts its execution.
  • If you comment t.join(); in main thread, then main and child thread run simultaneously and you can not expect the exact output.

Case - 2:  Waiting of child thread until completing of main thread.

This is little bit tricky. Lets us write a program on it.

class MyChildThread extends Thread  {
    //Declare a static variable of thread type, to hold main thread
    static Thread mt;
    public void run() {
        try {
            mt.join();
        }
        catch(InterruptedException exp) {
            exp.printStackTrace();
        }
        for(int i=0; i<5; i++) {
            System.out.println("Child Thread Running");           
        }
    }
}

public class ThreadJoinMain {
    public static void main(String[] args) throws InterruptedException {
        //Set the current thread in Static thread field
        MyChildThread.mt = Thread.currentThread();
       
        MyChildThread t = new MyChildThread();
        t.start();
        for(int j=0; j<5; j++) {
            System.out.println("Main Thread Running");
        }
    }
}

o/p:

Main Thread Running
Main Thread Running
Main Thread Running
Main Thread Running
Main Thread Running
Child Thread Running
Child Thread Running
Child Thread Running
Child Thread Running
Child Thread Running


Note:

  • In the above example, Child thread (MyChildThread) calls join() method on the main thread object. Hence child thread has to wait until completing of main thread.

Case - 3: Deadlock like situation

If main thread calls join() method on child class object and at same time child thread called join() method of main class object, then both thread will wait forever and the program will be stocked. This is something as Deadlock.

Case - 4:

If a thread calls join() method on the same thread, then the program will be stocked. In such case, thread has to wait infinite amount of time. This is also something  like Deadlock situation.

public class ThreadLock {
    public static void main(String[] args) throws InterruptedException {
        Thread.currentThread().join();
    }
}

This above code will go to deadlock situation.

.....
This ends Thread join() method. Comments are welcome…

Wednesday, 16 November 2016

Catching Child thread class exceptions in Main thread class and vice-versa in java

I came across a situation where we need to handle child thread class exceptions in main  thread class. Means which exception child class is throwing that to be handled by Main class.

Hope Most of the experience Java guys know this. This question normally asked in interview questions for experience people. I too came across this same question in one of my interview. That’s why I am sharing this program in my blog. Hope those who visit my page get benefit of it.

I have written two programs for this using.

  • UncaughtExceptionHandler
  • Executors Framework


Using UncaughtExceptionHandler: 

In this program I have used java 8 Lambda expression. If you not familiar with Java 8, you can comment java8 line and uncomment the java7 code.


import java.lang.Thread.UncaughtExceptionHandler;

/**
 * @author Bipin
 * This demonstrates how Main thread can see and print the exceptions generated by child thread
 *
 */
public class ChildThreadThrowingException {
       public static void main(String... args) {
            
             System.out.println("Main Thread");
             MyThread t = new MyThread();
            
// functional interface
   /*
   UncaughtExceptionHandler h = new UncaughtExceptionHandler()                                         {                          
              
                    @Override
                    public void uncaughtException(Thread thread, Throwable throwable) {
                           System.out.println(throwable);
                          
                    }
             };
             */
            
             
             // Using Java 8
      //UncaughtExceptionHandler h = (Thread thread, Throwable throwable) -> System.out.println(throwable);
            
//More advantage of Java 8             
       UncaughtExceptionHandler h = (thread, throwable) -> System.out.println(throwable);
            
             t.start();
             t.setUncaughtExceptionHandler(h);
            
       }
}

class MyThread extends Thread {
      
       private int x;

       public void run() {
             System.out.println("Child Thread");
             try {
                    x = 9/0;
                    System.out.println(x);
             }
             catch(ArithmeticException e) {
                    throw new ArithmeticException("Divide By Zero");
             }
            
       }
}

o/p:
Main Thread
Child Thread
java.lang.ArithmeticException: Divide By Zero


Using Executors Framework

import java.io.IOException;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/*
 * This class is going to use ExcecutorService and Future to handle the Exception
 */
public class MyExecutorService {

      
       public static void main(String[] args) {
            
             System.out.println("Main Thread");
            
             //Creates a thread pool that creates new threads as needed,
             //but will reuse previously constructed threads when they are available.
             ExecutorService executor = Executors.newCachedThreadPool();
            
             //Get the return object and used get() method that can wait for
             //the Callable to finish and then return the result.
             Future<Integer> future = executor.submit(new Callable<Integer>() {
                    /*                 
                     * Call method can either return a value or exception
                     */
                    @Override
                    public Integer call() throws Exception {
                          
                           Random randomnew Random();
                           int duration = random.nextInt(4000);
                          
                           if(duration > 2000) {
                                 throw new IOException("Sleep for "+duration+" miliseconds. Too much to sleep");
                           }
                          
                           System.out.println("Child Thread Starting");
                          
                           Thread.sleep(duration);
                          
                           System.out.println("Child Thread finished");
                          
                           return duration;
                    }
             });
            
             executor.shutdown();
            
             try {
                   
                    //Print the future result
                    System.out.println(future.get());
                   
             } catch (InterruptedException | ExecutionException e) {
                   
                    //Print the exception message that is set in call()
                    //System.out.println(e.getCause().getMessage()); //o/p: Sleep for 2766 miliseconds. Too much to sleep
                   
                    System.out.println(e.getMessage()); //o/p: java.io.IOException: Sleep for 2173 miliseconds. Too much to sleep
             }
       }

}


The End. Happy Codding. J

Thanks

Bipin