Recent Tutorials and Articles
    Introduction to Threads in Java
    Published on: 30th April 2014

    This tutorial provides introduction to the threading in Java along with a brief description of threads management, defining and starting a thread, and various thread operations such as interrupting, joining and pausing.

    Introduction to Threads

    Threads are quite useful as they help us execute tasks in-parallel/asynchronously (or just creating the illusion of the parallel execution in case of single core processors using time slicing) and hence increasing the throughput as when one thread is waiting for some resource to be available (like opening a file, connecting to database, waiting for the db query to return results, waiting for the data from file etc) , other thread can continue execution.

    Before we start discussing threads in detail, let's talk about execution environment. An execution env consists of heap memory, open files and other resources, and an application needs an execution environment in order to run.

    Threads provide this execution environment to the applications but unlike processes, each new thread created by the application (or JVM) doesn't result in the creation of a new execution environment (however each thread is assigned a stack which is not shared by other threads) and this is why threads sometimes are referred as lightweight processes. This feature of threads is what these make efficient but potentially problematic i.e. there may be the risk of data corruption due to concurrent access by multiple threads in shared memory.

    Moreover, in a multi-threaded env, there is no order which the threads will be executed in. There is a provision to set the priority of threads but there is no gauarntee that thread scheduler will use as this changes from one operating system to another.

    Threads Management Strategies

    Just like anything else in java, threads are represented as Objects. Each thread is associated with an instance of class Thread. Every application has got atleast one thread called main thread and more threads can be created from main thread.

    Usually application developers have following 2 basic strategies for using threads to create a concurrent application. We will however concentrate on first strategy in this tutorial. A separate tutorial will be covering the second strategy.

    1. Directly managing the threads i.e. creating a thread each time application needs to execute a task asynchronously
    2. Delegating the threads management to an executor i.e. passing the tasks to an executor which takes care of threads management for you

    Most of the time, application developers should opt second one as that keeps the application code clean as well as provides, depending on the type of executor benefits such as thread pooling, scheduling etc.

    Defining a Thread

    Firstly let's talk about the difference b/w defining and starting a thread. Defining a thread means defining the task (code) that will run in the new thread whereas starting a thread means calling start method on the instance of a thread. There are 2 ways to define a thread -

    1. Implement Runnable interface:
      public class RunnableDemo implements Runnable{
      	@Override
      	public void run() {
      		System.out.println("This is a demo thread defined by implementing Runnable interface");					
      	}
      }
      
      
    2. Subclass(extend) Thread class:
      public class ThreadDemo extends Thread{
      	@Override
      	public void run() {
      		System.out.println("This is a demo thread defined by extending Thread class");
      	}
      }
      
      
    Creating/Starting a Thread

    It is very important to note that just creating an instance of your thread/runnable class doesn't result into creation or starting of a thread instead it's just an instance of type Thread but there is no thread associated with it. In order to associate a thread to this instance, you have to call its start method which in turn calls run method having all the code that you wanted to execute asynchronously (in a separate thread).

    1. Starting a thread defined by implementing Runnable interface:
      Thread thread = new Thread(new RunnableDemo()); //Just an instance of thread type. Doesn't create/start a thread
      thread.start();  //Starts a new thread
      
      
    2. Starting a thread defined by extending Thread class:
      ThreadDemo threadDemo = new ThreadDemo(); //Just an instance of thread type. Doesn't create/start a thread
      threadDemo.start(); //Starts a new thread
      
      

    As you can see that second one is easier to use but is limited by the fact that your class can't extend any other class as well as it can't be passed to an executor (not allowing the strategy Delegating the threads management). Therefore, developers should generally, as possible, choose first way of starting a thread.

    Thread Operations

    Thread class has got many useful methods to perform various operations on threads some of which are as follows -

    Pausing Thread execution:

    Imagine a scenaio wherein your thread is looking for some resource to be available(or a flag to be set or you simply want to delay the processing for some time), you might want your thread to pause for some time before it checks again for that resource. In this scenario, sleep method of Thread class can be useful as this makes the thread to sleep atleast for the time passed as input parameter.

    There are 2 overloaded sleep methods one taking the time in milliseconds and other in both miliseconds and nanoseconds. In below example (since sleep method might throw InterruptedException , you would need to handle/propagate that), first sleep method call results into the thread being into sleep for atleast 2000ms (2sec) while the later one, for 2000ms and 5000ns(nanoseconds) -

    try {
    	Thread.sleep(2000);
    	Thread.sleep(2000, 5000);
    } catch (InterruptedException e) {
    	// TODO Auto-generated catch block
    	e.printStackTrace();
    }
    
    

    In following example, we are pausing main thread for 10 secs-

    ThreadSleepDemo.java
    package com.sts.allprogtutorials;
    
    import java.util.Date;
    /**
     * @author Sain Technology Solutions
     *
     */
    public class ThreadSleepDemo {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		System.out.println("main thread started at: " + new Date());
    		try {
    			Thread.sleep(10000); //Sleep for 10 secs
    		} catch(InterruptedException interruptedException) {
    			interruptedException.printStackTrace();
    		}
    		System.out.println("main thread resumed at: " + new Date());
    	}
    }
    
    

    Here is the output of the above program and we can see that main thread resumes after atleast 10 secs.

    Output
    main thread started at: Thu May 01 08:18:15 IST 2014
    main thread resumed at: Thu May 01 08:18:25 IST 2014
    
    

    Interrupting Thread execution:

    We know that how we can pause a thread for a specified time but how do we stop a thread? This is where thread interrupts come into picture. An interrupt is a signal to thread that it should stop executing(though it completely depends on how developers have handled interrupts as they might want to continue ever after receiving the interrupt).

    Next question comes how developers can handle interrupts? This is achieved in 2 ways -

    1. Handling InterruptedException thrown by methods supporting interruption:

      Some of the thread operations support/respond-to interrupts by throwing InterruptedException. sleep and join are 2 of such operations/methods.

      Let's change our sleep method example a bit by creating a new thread (as we need a thread to interrupt other thread) to demonstrate the interruption. In this example, main thread interrupts the other thread by calling interrupt method on its instance.

      ThreadSleepInterruptDemo.java
      package com.sts.allprogtutorials;
      
      import java.util.Date;
      /**
       * @author Sain Technology Solutions
       *
       */
      public class ThreadSleepInterruptDemo implements Runnable{
      	/**
      	 * @param args
      	 */
      	public static void main(String[] args) {
      		System.out.println("main thread started");
      		
      		//Create an instance of Thread by passing our runnable task containing the sleep logic
      		Thread thread = new Thread(new ThreadSleepInterruptDemo());
      		thread.start();  //Start a new thread
      		
      		//Interrupt the thread by calling interrupt method
      		thread.interrupt();
      	}
      
      	@Override
      	public void run() {
      		System.out.println("New thread started at: " + new Date());
      		try {
      			Thread.sleep(10000);
      		} catch(InterruptedException interruptedException) {
      			System.out.println("Thread interrupted before 10 secs, so exiting");
      			return; // Developers may choose to go ahead with execution by removing this return 
      		}
      		System.out.println("New thread resumed at: " + new Date());
      		
      	}
      }
      
      
      Output
      main thread started
      New thread started at: Thu May 01 08:53:00 IST 2014
      Thread interrupted before 10 secs, so exiting
      
      

      As we can see that thread was interrupted before it completed its processing and since at the time of interrupt thread was sleeping, it threw an InterruptedException where we have stopped thread execution by returning.

    2. Checking whether a thread is interrupted by invoking Thread.interrupted method:

      It is quite possible that thread execution doesn't involve any of the operation supporting interrupts (i.e. none of the methods called in thread throw InterruptedException).What do we do in this scenarion? How do developers get to know whether a thread has been interrupted?

      In this scenarion, we can use Thread.interrupted method to check whether a thread has been interrupted. Following example illustrates this approach wherein we are calling Thread.interrupted method in a loop to see whether the thread has been interrupted -

      ThreadInterruptDemo.java
      package com.sts.allprogtutorials;
      
      import java.util.Date;
      /**
       * @author Sain Technology Solutions
       *
       */
      public class ThreadInterruptDemo implements Runnable{
      	/**
      	 * @param args
      	 */
      	public static void main(String[] args) {
      		System.out.println("main thread started");
      		
      		//Create an instance of Thread by passing our runnable task
      		Thread thread = new Thread(new ThreadInterruptDemo());
      		thread.start();  //Start a new thread
      		
      		//you can call getName or getId to recognise threads
      		System.out.println("Going to interrupt thread: " + thread.getName()); 
      		
      		
      		//Interrupt the thread by calling interrupt method
      		thread.interrupt();
      	}
      
      	@Override
      	public void run() {
      		System.out.println("New thread started at: " + new Date());
      		for(int i = 0; i <50; i++) {
      			if(Thread.interrupted()) {
      				System.out.println("Thread interrupted before 50 iterations, current counter value: " + i);
      				return;
      			}
      		}
      	}
      }
      
      
      Output
      main thread started
      Going to interrupt thread: Thread-0
      New thread started at: Thu May 01 10:13:06 IST 2014
      Thread interrupted before 50 iterations, current counter value: 0
      
      

      As you would have noticed, we have called getName method on thread instance to get the name of newly created thread. There are many other similar methods in Thread class that can come handy like getting/setting name, thread group, priority etc.

    Joining Threads execution:

    You might end up in a situation where you need to wait for a thread execution to finish before moving forward. join method of Thread instance can be used to achieve this functionality. Let's consider following code examples- one without join method & other with join method.

    ThreadWithoutJoinDemo.java
    package com.sts.allprogtutorials;
    
    import java.util.Date;
    
    /**
     * @author Sain Technology Solutions
     *
     */
    public class ThreadWithoutJoinDemo implements Runnable {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		System.out.println("main thread started");
    		
    		//Create an instance of Thread by passing our runnable task containing the sleep logic
    		Thread thread = new Thread(new ThreadWithoutJoinDemo());
    		thread.start();  //Start a new thread
    		
    		System.out.println("main thread ended");
    	}
    
    	@Override
    	public void run() {
    		System.out.println("New thread started at: " + new Date());
    		try {
    			Thread.sleep(1000);
    		} catch(InterruptedException interruptedException) {
    			return; // Developers may choose to go ahead with execution by removing this return 
    		}
    		System.out.println("New thread ended at: " + new Date());
    		
    	}
    }
    
    
    Output(ThreadWithoutJoinDemo)
    main thread started
    main thread ended
    New thread started at: Thu May 01 10:25:03 IST 2014
    New thread ended at: Thu May 01 10:25:04 IST 2014
    
    
    ThreadJoinDemo.java
    package com.sts.allprogtutorials;
    
    import java.util.Date;
    
    /**
     * @author Sain Technology Solutions
     *
     */
    public class ThreadJoinDemo implements Runnable {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		System.out.println("main thread started");
    		
    		//Create an instance of Thread by passing our runnable task containing the sleep logic
    		Thread thread = new Thread(new ThreadJoinDemo());
    		thread.start();  //Start a new thread
    		
    		//Join the other thread by calling join on its instance 
    		try {
    			thread.join();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		
    		System.out.println("main thread ended");
    	}
    
    	@Override
    	public void run() {
    		System.out.println("New thread started at: " + new Date());
    		try {
    			Thread.sleep(1000);
    		} catch(InterruptedException interruptedException) {
    			return; // Developers may choose to go ahead with execution by removing this return 
    		}
    		System.out.println("New thread ended at: " + new Date());
    		
    	}
    }
    
    
    Output(ThreadJoinDemo)
    main thread started
    New thread started at: Thu May 01 10:59:14 IST 2014
    New thread ended at: Thu May 01 10:59:15 IST 2014
    main thread ended
    
    

    As we can see that if we don't use join method then main thread finishes before the other thread however if we join the other thread then main thread waits and finishes after the other thread is done processing.

    Thank you for reading through the tutorial. In case of any feedback/questions/concerns, you can communicate same to us through your comments and we shall get back to you as soon as possible.

    Published on: 30th April 2014

    Comment Form is loading comments...