A thread is a light-weight smallest part of a process that can run concurrently with the other parts(other threads) of the same process. Threads are independent because they all have separate path of execution that’s the reason if an exception occurs in one thread, it doesn’t affect the execution of other threads. All threads of a process share the common memory. The process of executing multiple threads simultaneously is known as multithreading.

Thread life cycle

As the process has several states, similarly a thread exists in several states. A thread can be in the following states:

  1. New: Ready to run. The thread is in new state if you create an instance of Thread class but before the invocation of start() method.
  2. Runnable: The thread is in runnable state after invocation of start() method, but the thread scheduler has not selected it to be the running thread.
  3. Running: The thread is in running state if the thread scheduler has selected it.
  4. Non-Runnable (Waiting): This is the state when the thread is still alive, but is currently not eligible to run. Temporarily its is not active or under execution or waiting for resources.  A 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.
  5. Terminated(Dead): Halts the execution immediately and never resumes. A thread is in terminated or dead state when its run() method exits.

 

The java.lang.Thread class contains a static State enum – which defines its potential states. During any given point of time, the thread can only be in one of these states:

  • NEW – newly created thread that has not yet started the execution
  • RUNNABLE – either running or ready for execution but it’s waiting for resource allocation
  • BLOCKED – waiting to acquire a monitor lock to enter or re-enter a synchronized block/method
  • WAITING – waiting for some other thread to perform a particular action without any time limit
  • TIMED_WAITING – waiting for some other thread to perform a specific action for a specified period
  • TERMINATED – has completed its execution

 

Thread Priorities

Each thread has its own priority. Thread priority is an absolute integer value. Thread priority decides only when a thread switches from one running thread to next, called context switching. Priority does increase the running time of the thread or gives faster execution.

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).

 

Multithreading

Multithreading in java is a process of executing two or more threads simultaneously to maximum utilization of CPU. Multithreaded applications are where two or more threads run concurrently; hence it is also known as Concurrency in Java. This multitasking is done, when multiple processes share common resources like CPU, memory, etc.

Each thread runs parallel to each other. Threads don’t allocate separate memory area; hence it saves memory. Also, context switching between threads takes less time.

When a CPU switches from executing one thread to executing another, the CPU needs to save the local data, program pointer etc. of the current thread, and load the local data, program pointer etc. of the next thread to execute. This switch is called a “context switch”. Context switching isn’t cheap. You don’t want to switch between threads more than necessary.

 

Thread Creation

There are two ways to create a thread in Java:

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

Read more at : Thread and Runnable | Java

 

Thread Synchronization

In multithreading, there is the asynchronous behavior of the programs. If one thread is writing some data and another thread which is reading data at the same time, might create inconsistency in the application.

Java has provided synchronized methods to implement synchronized behavior. In this approach, once the thread reaches inside the synchronized block, then no other thread can call that method on the same object. All threads have to wait till that thread finishes the synchronized block and comes out of that.

At times when more than one thread try to access a shared resource, we need to ensure that resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. The synchronization keyword in java creates a block of code referred to as critical section.

// Synchronized Syntax
synchronized (object)
{
  //statement to be synchronized
}

Using Synchronized methods is a way to accomplish synchronization. If you have to synchronize access to an object of a class or you only want a part of a method to be synchronized to an object then you can use synchronized block for it.

// Java Synchronization example
class Print
{
  public void display(String msg)
  {
    System.out.print ("["+msg);

    try
    {
      Thread.sleep(1000);
    }
    catch(InterruptedException e)
    {
      e.printStackTrace();
    }
    
    System.out.print ("]");
  }
}

class Print2
{
  // Synchronized method
  public synchronized void display(String msg)
  {
    System.out.print ("["+msg);
    
    try
    {
      Thread.sleep(1000);
    }
    catch(InterruptedException e)
    {
      e.printStackTrace();

    }
    
    System.out.print ("]");    
  }
}

class Second extends Thread
{
  String msg;
  Print  fobj;
  Print2 fobj2;
  
  Second (Print fp, Print2 fp2, String str)
  {
    fobj   = fp;
    fobj2  = fp2;
    msg    = str;
    start();
  }

  public void run()
  {
    // Synchronized block
    synchronized(fobj)
    {
      fobj.display(msg);
    }
  }
}

public class Syncro
{
  public static void main (String[] args)
  {
    Print fnew  = new Print();
    Print fnew2 = new Print2();
    Second ss   = new Second(fnew, fnew2, "welcome");
    Second ss1  = new Second (fnew,fnew2, "new");
    Second ss2  = new Second(fnew, fnew2, "programmer");
  }
}

In the above program, object fnew and fnew2 are shared by all the three running threads (ss, ss1 and ss2) to call the shared method(void display). Result will be unsynchronized (race condition) when these methods are not synchronized.

race condition is a special condition that may occur inside a critical section. A critical section is a section of code that is executed by multiple threads and where the sequence of execution for the threads makes a difference in the result of the concurrent execution of the critical section.

When the result of multiple threads executing a critical section may differ depending on the sequence in which the threads execute, the critical section is said to contain a race condition. The term race condition stems from the metaphor that the threads are racing through the critical section, and that the result of that race impacts the result of executing the critical section.

When we use synchronized keyword with a method, it acquires a lock in the object for the whole method. It means that no other thread can use any synchronized method until the current thread, which has invoked it’s synchronized method, has finished its execution. Synchronized block acquires a lock in the object only between parentheses after the synchronized keyword. This means that no other thread can acquire a lock on the locked object until the synchronized block exits. But other threads can access the rest of the code of the method.

 

Inter-thread Communication

Java provide benefits of avoiding thread pooling using inter-thread communication. The wait(), notify(), and notifyAll() methods of Object class are used for this purpose. These method are implemented as final methods in Object, so that all classes have them. All the three method can be called only from within a synchronized context.

  • wait() tells calling thread to give up monitor and go to sleep until some other thread enters the same monitor and call notify.
  • notify() wakes up a thread that called wait() on same object.
  • notifyAll() wakes up all the thread that called wait() on same object.

Read more on : Thread Signaling

 

Thread Deadlock

Deadlocks are a set of blocked processes each holding a resource and waiting to acquire a resource held by another process. For instance, if thread 0 is holding lock on resource 1 and tries to lock on  resource 2, and thread 1 has already locked resource 2 and tries to lock on resource 1, a deadlock arises. They will remain blocked on each their object, A and B, forever. This situation is a deadlock.