Java Threads

Thread is a lightweight sub-process with a smallest unit of processing. Thread execution path is separate. Threads are independent. If any error or exception occured in one single thread it will not effect on other threads. It uses a shared memory.

Difference between Process and Thread

To better understand this question, let’s first take a look at what is a Program. A Program is an executable file containing a set of instructions and passively stored on disk. One program can have multiple processes. For example, the Chrome browser creates a different process for every single tab.

A Process means a program is in execution. When a program is loaded into the memory and becomes active, the program becomes a process. The process requires some essential resources such as registers, program counter, and stack.

A Thread is the smallest unit of execution within a process.

The following process explains the relationship between program, process, and thread.

  1. 1. The program contains a set of instructions.
  2. 2. The program is loaded into memory. It becomes one or more running processes.
  3. 3. When a process starts, it is assigned memory and resources. A process can have one or more threads. For example, in the Microsoft Word app, a thread might be responsible for spelling checking and the other thread for inserting text into the doc.

Main differences between process and thread:

  1. Processes are usually independent, while threads exist as subsets of a process.
  2. Each process has its own memory space. Threads that belong to the same process share the same memory.
  3. A process is a heavyweight operation. It takes more time to create and terminate.
  4. Context switching is more expensive between processes.
  5. Inter-thread communication is faster for threads.

Multitasking

The process of executing a multiple task simultaneously is nothing but multitasking. It can be achived two different ways.

  1. 1. Multiprocessing : Execution of a multiple task simultaneously using processor is nothing but Multiprocessing. It is a heavy weight process and it will allocate separate memory for each individually task execution.
  2. 2. Multithreading : Execution of multiple task simultaneously using threads is nothing but Multithreading. It is a lightweight process and it will use the shared memory while execution of a program.

Thread Life cycle in java

Different stages in thread life cycle.




  1. New: Whenever a new thread is created, it is always in the new state.
  2. Runnable: A thread, that is ready to run is then moved to the runnable state. In the runnable state, the thread may be running or may be ready to run at any given instant of time.
  3. Running: When the thread gets the CPU, it moves from the runnable to the running state. Generally, the most common change in the state of a thread is from runnable to running and again back to runnable.
  4. Blocked: The thread will be in blocked state when it is trying to acquire a lock but currently the lock is acquired by the other thread. The thread will move from the blocked state to runnable state when it acquires the lock.
  5. Waiting: Sometimes, a thread transitions to the waiting state while the thread waits for another thread to perform a task. A thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
  6. Time waiting: A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
  7. Terminated (Dead): A runnable thread enters the terminated state when it completes its task or otherwise terminates.

How to create a thread

Thread can be created two ways:

  1. 1. By extending Thread class
  2. 2. By implementing Runnable interface

Thread class

Thread class provide constructors and methods to create and perform operations on a thread.Thread class extends Object class and implements Runnable interface.

Constructos in Thread class
Constructor Description
Thread() Can create a Thread object using default constructor.
Thread(String name) Can create a Thread object by passing the thread name in constructor.
Thread(Runnable r) Can create a Thread object by passing runnable interface in constructor.
Thread(Runnable r,String name) Can create a Thread object by passing thread name and runnable in constructor.
Commonly used methods of Thread class:
Method name Description
public void run(): is used to perform action for a thread.
public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.
public void join(): waits for a thread to die.
public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
public int getPriority(): returns the priority of the thread.
public int setPriority(int priority): changes the priority of the thread.
public String getName(): returns the name of the thread.
public void setName(String name): changes the name of the thread.
public Thread currentThread(): returns the reference of currently executing thread.
public int getId(): returns the id of the thread.
public Thread.State getState(): returns the state of the thread.
public boolean isAlive(): tests if the thread is alive.
public void yield(): causes the currently executing thread object to temporarily pause and allow other threads to execute.
public void suspend(): is used to suspend the thread(depricated).
public void resume(): is used to resume the suspended thread(depricated).
public void stop(): is used to stop the thread(depricated).
public boolean isDaemon(): tests if the thread is a daemon thread.
public void setDaemon(boolean b): marks the thread as daemon or user thread.
public void interrupt(): interrupts the thread.
public boolean isInterrupted(): tests if the thread has been interrupted.
public static boolean interrupted(): tests if the current thread has been interrupted.
Runnable interface:

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. Runnable interface have only one method named run().

Method name Description
public void run(): is used to perform action for a thread.
Starting a thread:

The start() method of Thread class is used to start a newly created thread. It performs the following tasks:

  1. 1. A new thread starts(with new callstack).
  2. 2. The thread moves from New state to the Runnable state.
  3. 3. When the thread gets a chance to execute, its target run() method will run.

Thread Example Program by extending Thread class

  class ExampleThread extends Thread {  
      public void run(){  
          System.out.println("thread is running...");  
      }  
      public static void main(String args[]){  
          ExampleThread t1=new ExampleThread();  
          t1.start();  
      }  
  }  

Thread Example Program by implementing runnable interface

  package com.java.session.thirteen;

  public class ThreadExample1 implements Runnable {
      @Override
      public void run() {
          System.out.println("Started runnable interface....!");
      }

      public static void main(String[] args) {
          ThreadExample1 t1 = new ThreadExample1();
          t1.run();
      }
  } 

Joining Threads in Java

Thread has join() method, this method is used to join the another thread once execution of current thread.
Example: In this example, we're creating a class RunnableDemo by implementing Runnable interface. RunnableDemo class has run() method implementation. In main class TestThread, we've created the RunnableDemo objects and using those objects we've created two Thread objects. When Thread.start() method is called on each thread objects, threads start processing and program is executed. Using join() method, we're blocking the current thread which ensure that once thread is complete then only next thread will start.


  package com.java.session.thirteen;

  public class TestThreadJoin {
      public static void main(String[] args) throws InterruptedException {
          Thread t1 = new Thread(new RunnableDemo(), "Thread-1");
          Thread t2 = new Thread(new RunnableDemo(), "Thread-2");
          Thread t3 = new Thread(new RunnableDemo(), "Thread-3");
          t1.start();
          t1.join();
          t2.start();
          t2.join();
          t3.start();
      }
  }

  class RunnableDemo implements Runnable {

      @Override
      public void run() {
          System.out.println("Thread :: "+Thread.currentThread().getName()+" started");
          for(int i=0; i<5; i++) {
              System.out.println("Thread :: "+Thread.currentThread().getName()+ " i "+i+ " Running");
          }
          System.out.println("Thread :: "+Thread.currentThread().getName()+ " Dead");
      }
  }

Thread Scheduler

Thread Scheduler is nothing but schudling a task multiple time for a specific period of time. Java provides a java.util.concurrent.ScheduledExecutorService interface which is a subinterface of ExecutorService interface, and it supports future periodic execution of tasks/threads.

Example: The following TestThread program shows usage of ScheduledExecutorService interface in thread based environment to schedule a task to run after 2 seconds at interval of 2 seconds in time period of 10 seconds showcasing usage of scheduleAtFixedRate() and schedule() methods.


  package com.java.session.thirteen;

  import java.util.concurrent.*;

  public class ThreadSchedulerExample {
      public static void main(String[] args) {
          final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
          ScheduledFuture<?> beepHandler = scheduler.scheduleAtFixedRate(new BeepTask(), 0, 2, TimeUnit.SECONDS);
          scheduler.schedule(new Runnable() {
              @Override
              public void run() {
                  beepHandler.cancel(true);
                  scheduler.shutdown();
              }
          }, 10, TimeUnit.SECONDS);
      }

      static class BeepTask implements Runnable {

          @Override
          public void run() {
              System.out.println("Beep Executed...!");
          }
      }
  }

Thread pool

A thread pool is a collection of pre-initialized threads. At any program start up if we want to create a pool of thread then will go with the concept called thread pool. This is mostly used in server side programming. Whenever a server started thread pool will be created and based on the request server will pick the available thread from the thread pool, once it's job is completed then it will return back to the pool. If the pool contains no accessible thread, the server waits till one becomes free.

Creating Thread Pools in Java

4 different types of thread pool can be created. using below methods

Method Description
public static ExecutorService newCachedThreadPool() Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
public static ExecutorService newFixedThreadPool(int nThreads) Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
public static ExecutorService newWorkStealingPool() Creates a work-stealing thread pool using all available processors as its target parallelism level.
Thread Pool Using newFixedThreadPool() Method

  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.ThreadPoolExecutor;
  import java.util.concurrent.TimeUnit;

  public class TestThread {
    
    public static void main(final String[] arguments) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        // Cast the object to its class type
        ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

        //Stats before tasks execution
        System.out.println("Largest executions: "
          + pool.getLargestPoolSize());
        System.out.println("Maximum allowed threads: "
          + pool.getMaximumPoolSize());
        System.out.println("Current threads in pool: "
          + pool.getPoolSize());
        System.out.println("Currently executing threads: "
          + pool.getActiveCount());
        System.out.println("Total number of threads(ever scheduled): "
          + pool.getTaskCount());

        executor.submit(new Task());
        executor.submit(new Task());
        executor.submit(new Task());
        executor.submit(new Task());

        //Stats after tasks execution
        System.out.println("Core threads: " + pool.getCorePoolSize());
        System.out.println("Largest executions: "
          + pool.getLargestPoolSize());
        System.out.println("Maximum allowed threads: "
          + pool.getMaximumPoolSize());
        System.out.println("Current threads in pool: "
          + pool.getPoolSize());
        System.out.println("Currently executing threads: "
          + pool.getActiveCount());
        System.out.println("Total number of threads(ever scheduled): "
          + pool.getTaskCount());

        executor.shutdown();
    }  

    static class Task implements Runnable {

        public void run() {
          
          try {
              Long duration = (long) (Math.random() * 5);
              System.out.println("Running Task! Thread Name: " +
                Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(duration);
              
              System.out.println("Task Completed! Thread Name: " +
                Thread.currentThread().getName());
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
        }
    }
  }

Main Thread in Java

Whenever we run a Java program, main thread is created automatically. This thread is responsible for execution of java program. The main thread is created by the JVM automatically when a program starts. But you can control a Main thread by using different Thread methods and techniques.

  1. 1. sleep() Method
  2. 2. join() Method
  3. 3. interrupt() Method

Example of Java Main Thread

  package com.java.session.thirteen;

  public class TestThread {
      public void printName() {
          System.out.println("Thread Name: " + Thread.currentThread().getName());
          System.out.println("Thread Priority: " +Thread.currentThread().getPriority());
      }
      public static void main(String args[]) {
          TestThread thread = new TestThread();
          thread.printName();
      }
  }

Thread Priority

Every Java thread has a priority that helps the operating system determine the order in which threads are scheduled. You can get and set the priority of a Thread. Thread class provides methods and constants for working with the priorities of a Thread. Threads with higher priority are more important to a program and should be allocated processor time before lower-priority threads. However, thread priorities cannot guarantee the order in which threads execute and are very much platform dependent.

Java thread priorities are in the range between MIN_PRIORITY (a constant of 1) and MAX_PRIORITY (a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5).

  1. 1. MIN_PRIORITY: Specifies the minimum priority that a thread can have.
  2. 2. NORM_PRIORITY: Specifies the default priority that a thread is assigned.
  3. 3. MAX_PRIORITY: Specifies the maximum priority that a thread can have.

Examples of Thread Priority

  package com.java.session.thirteen;

  public class ThreadPriorityDemo {
      public static void main(String[] args) {
          ThreadDemo t1 = new ThreadDemo();
          ThreadDemo t2 = new ThreadDemo();
          ThreadDemo t3 = new ThreadDemo();
          t1.setPriority(Thread.MAX_PRIORITY);
          t2.setPriority(Thread.MIN_PRIORITY);
          t3.setPriority(Thread.NORM_PRIORITY);
          t1.start();
          t2.start();
          t3.start();
      }
  }

  class ThreadDemo extends Thread {
      public void run() {
          System.out.println("ThreadName "+Thread.currentThread().getName()+" Priority "+Thread.currentThread().getPriority());
          for(int i=0; i<4; i++) {
              System.out.println("Thread: " + Thread.currentThread().getName() + ", " + i);
          }

          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  }


Daemon Thread

A Daemon thread is created to support the user threads. It generallty works in background and terminated once all the other threads are closed. Garbage collector is one of the example of Daemon thread.

Characteristics of a Daemon Thread
  1. 1. A Daemon thread is a low priority thread.
  2. 2. A Daemon thread is a service provider thread and should not be used as user thread.
  3. 3. JVM automatically closes the daemon thread(s) if no active thread is present and revives it if user threads are active again.
  4. 4. A daemon thread cannot prevent JVM to exit if all user threads are done.
Methods for Java Daemon Thread
Method Description
Thread.setDaemon() Method Marks this thread as either a daemon thread or a user thread.
Thread.isDaemon() Method Checks if this thread is a daemon thread.
Example of Java Daemon Thread

  class ThreadDemo extends Thread {
    ThreadDemo( ) {
    }
  
    public void run() {
        System.out.println("Thread  " + Thread.currentThread().getName() 
          + ", is Daemon: " + Thread.currentThread().isDaemon());
    }
    public void start () {     
        super.start();
    }
  }
  public class TestThread {
    public static void main(String args[]) {
      ThreadDemo thread1 = new ThreadDemo();
      ThreadDemo thread2 = new ThreadDemo();
      ThreadDemo thread3 = new ThreadDemo();
        thread3.setDaemon(true);
      thread1.start();
      thread2.start();
      thread3.start();
    }
  }