Thread – direction or path that is taken while a program is executed

  1. Below code would explain how dirty read happens when multiple thread(2 threads) tries to access Instance variable at once from two different class objects
  2. Below we have 3 classes, One for Printing Report and Other for removing the report printed. Third for tracking the report status
  3. The Output of the code would be Consistently 0 every time which is expected when the number of reports to be printed is in range of less than 100. However the output changes with more the no of reports to be printed. I.E. totalReportsToBePrinted = 10000000
  4. This happens because for lower value of reports to be printed the thread executes fast with out context switching however for higher values other thread(RemovePrintedReports thread takes control before PrintExcelReports get completed) takes control which leads to inconsistency
  5. The Same code would return 0 every time if one thread(PrintExcelReports) completes before other(RemovePrintedReports) as below when we use join and didn’t start both the threads at once.
    .
    .
            t1.start();
            t1.join();
            
            t2.start();
            t2.join();
    
    .
    .
    

PrintExcelReports.java

public class PrintExcelReports implements Runnable {
    TotalReportCount totalReportCount;

    public PrintExcelReports(TotalReportCount totalReportCount) {
        this.totalReportCount = totalReportCount;
    }

    int totalReportsToBePrinted = 1000000;

    @Override
    public void run() {
        for(int i=0;i<totalReportsToBePrinted;i++){
            totalReportCount.totalReportsCntVal -= i;
        }
    }
}

RemovePrintedReports.java

public class RemovePrintedReports implements Runnable {
    TotalReportCount totalReportCount;

    public RemovePrintedReports(TotalReportCount totalReportCount) {
        this.totalReportCount = totalReportCount;
    }

    int totalReportsToBePrinted = 1000000;

    @Override
    public void run() {
        for(int i=0;i<totalReportsToBePrinted;i++){
            totalReportCount.totalReportsCntVal -= i;
        }
    }
}

ReportCurrentStatus.java

public class ReportCurrentStatus {
    public static void main(String[] args) throws InterruptedException {
        TotalReportCount objTotalReportCount = new TotalReportCount();
        objTotalReportCount.totalReportsCntVal = 0;

        PrintExcelReports objPrinter1 = new PrintExcelReports(objTotalReportCount);
        RemovePrintedReports objPrinter2 = new RemovePrintedReports(objTotalReportCount);

        Thread t1 = new Thread(objPrinter1);
        Thread t2 = new Thread(objPrinter2);

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println(objTotalReportCount.totalReportsCntVal);
    }
}

Output when totalReportsToBePrinted is greater than 1000

RANDOM NUMBER

Output when totalReportsToBePrinted is less than 100

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

NEW Thread (or a Born Thread) is a thread that’s been created but not yet started.
It remains in this state until we start it using the start() method

NewState.java

public class NewState implements Runnable{
    public void run(){
        System.out.println("I am in new State");
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
       Thread objThread = new Thread(new NewState());
       System.out.println(objThread.getState());
    }
}

Output

NEW

Runnable When we’ve created a new thread and called the start() method on that, it’s moved from NEW to RUNNABLE state. Threads in this state are either running or ready to run, but
they’re waiting for resource allocation from the system. In a multi-threaded environment, the Thread-Scheduler (which is part of JVM) allocates a fixed amount of time to each thread. So it runs for a particular amount of time, then leaves the control to other RUNNABLE threads.

RunnableState .java

public class RunnableState implements Runnable{
    public void run(){
        System.out.println("I would be in Runnable State");
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
       Thread objRThread = new Thread(new RunnableState());
       objRThread.start();
       System.out.println(objRThread.getState());
    }
}

Output

RUNNABLE
I would be in Runnable State

This is the state of a dead thread. It’s in the TERMINATED state when it has either finished execution or was terminated abnormally.
TerminatedState.java

public class TerminatedState implements Runnable{
    public void run(){
        Thread objNewState = new Thread(new NewState());
        objNewState.start();
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
       Thread objTState = new Thread(new TerminatedState());
       objTState.start();
       objTState.sleep(1000);
       System.out.println("T1 : "+ objTState.getState());
    }
}

Output

I am in new State
T1 : TERMINATED

A thread is in the BLOCKED state when it’s currently not eligible to run. It enters this state when it is waiting for a monitor lock and is trying to access a section of code that is locked by some other thread.
BlockedState.java

public class BlockedState implements Runnable{
    public void run(){
      blockedResource();
    }

    public static synchronized void blockedResource(){
        while(true){
            //Do Nothing
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread objB1Thread = new Thread(new BlockedState());
        Thread objB2Thread = new Thread(new BlockedState());

        objB1Thread.start();
        objB2Thread.start();

        Thread.sleep(1000);

        System.out.println(objB1Thread.getState());
        System.out.println(objB2Thread.getState());
        System.exit(0);
    }
}

Output

RUNNABLE
BLOCKED

A thread is in WAITING state when it’s waiting for some other thread to perform a particular action. According to JavaDocs, any thread can enter this state by calling any one of the following
object.wait() (or) thread.join() (or) LockSupport.park()

WaitingState.java

public class WaitingState implements Runnable{
    public void run(){
        Thread objWaitState = new Thread(new SleepState());

        objWaitState.start();

        try {
            objWaitState.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

SleepState.java

public class SleepState implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
       Thread objWaitingThread = new Thread(new WaitingState());
       objWaitingThread.start();
       objWaitingThread.sleep(1000);
       System.out.println("T1 : "+ objWaitingThread.getState());
       System.out.println("Main : "+Thread.currentThread().getState());
    }
}

Output

T1 : WAITING
Main : RUNNABLE

A thread is in TIMED_WAITING state when it’s waiting for another thread to perform a particular action within a stipulated amount of time. According to JavaDocs, there are five ways to put a thread on TIMED_WAITING state:
thread.sleep(long millis) (or) wait(int timeout) (or) wait(int timeout, int nanos) thread.join(long millis) (or) LockSupport.parkNanos (or) LockSupport.parkUntil

TimedWaitState.java

public class TimedWaitState implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread objTWState = new Thread(new TimedWaitState());
        objTWState.start();
        Thread.sleep(2000);
        System.out.println("T1 : "+ objTWState.getState());
    }
}

Output

T1 : TIMED_WAITING