Threads in java

Definition: A thread is a single sequential flow of control inside a program. A thread is like a sequential programs which has a beginning, has a sequence, has an end and has a single point of execution at any given point of time during the runtime of the thread.

Some definitions of thread consider a thread as a lightweight process because it runs within the context of a full-blown program and consume less system resources as compared to process.

Thread is not a program but runs inside a program and multiple threads running inside the same program share same resources and are less insulated from each other than separate processes are. They share memory area, same file handles, and other per-process state.

Like processes, threads are independent and concurrent paths of execution through a program. Each thread has its own stack, its own local variables and its own program counter.

What is multi-threading?

There is no fun in a program which has a single thread running inside, rather its about the use of multiple threads running and performing different task at the same time in a single program. So, multi-threading is a way to allow multiple activities coexist within a single program.

A process can support multiple threads to execute simultaneously and asynchronously to each other.

Multiple threads within a process share the same memory address space, which means they have access to the same resources like variables and objects, While this makes it easy for threads to share information with each other, so we must take care to ensure that multiple threads do not interfere with other threads in the same process.

Java is the first programming language to explicitly provides multi-threading feature within the language itself rather than treating threading as facility provided by underlying operating system.

Every program in java use threads

Every Java program has at least one thread – the main thread. JVM creates the main thread when a Java program get started and calls the program’s main() method within that thread.

JVM also creates some background threads which are mostly invisible to the programmer. For example, threads related with garbage collection, object finalization and other JVM housekeeping tasks.

In Java each thread is created and controlled by the Thread class of package java.lang. This class provides the Thread APIs and all generic behavior like starting, sleeping, running, yielding and priority for threads.

Below are 6 differences between thread and process:

  • A program in execution is called process while a thread is a subset of the process.
  • Both process and thread are independent paths of execution but a process can contain multiple threads. A thread is a smallest part of the process which can execute concurrently with other threads of the process.
  • Each process has its own separate memory space and unique process identifier(PID) while each threads inside a process share the same memory space and has its own stack which is shared with other threads.
  • A process communicate with other process by using inter-process communication which is limited and expensive while a thread can communicate with other threads directly within the same process by using inter-thread communication like wait and notify methods in java which is much simpler and cheaper than inter-process communication.
  • Process creation requires duplication of parent process while its easy to create a new thread by creating an object of Thread class and calling its start method.
  • Threads have less overhead as compared to Process in terms of metadata, context switching and memory space requirement.

How you will implement thread in java?

There are several ways to implement a thread in java, following are the most common ways:

  • Implements Runnable interface
  • Extends Thread class
  • Use anonymous Runnable implementation
  • Use Executor Service

Implements Runnable interface

class MyThread implements Runnable{
	public void run(){

Extends Thread class

class MyThread extends Thread {
      public MyThread() {
      public void run() {
            // DO SOMETHING

Use anonymous Runnable implementation

class MyThread {
      public static void myMethod() {
            // DO SOMETHING ...
      public static void main(String[] arg){
        Thread t = new Thread(){
            public void run() {

Use Executor Service

ExecutorService es = Executors.newFixedThreadPool(5);
es.execute(new Runnable() {
      public void run() {
            // DO SOMETHING ...

Note:- All above methods of implementing thread internally use Runnable interface.

What is java memory model

The Java memory model defines how the Java virtual machine works with the computer’s memory (RAM). Understanding of Java Memory Model is very important if you want to develop a highly concurrent application. Below are the important points regarding the Java Memory Model:

  • The Java programming language specifies a memory model for shared memory multiprocessors that supports high-performance implementations.
  • Memory that can be shared between threads is called shared memory or heap memory. All instance fields, static fields, and array elements are stored in heap memory.
  • The Java Memory Model defines how threads in Java interact through memory. It ensures that all threads see a consistent value for the variable.
  • The Java Memory Model describes, given a program and an execution trace of that program, whether the execution trace is a legal execution of the program.
  • The Java Memory Model provides a great deal of freedom for the implementer to perform a myriad of code transformations.
  • It must be possible for the Java Memory Model to decide when it can commit actions that take place in a finalizer.
  • Local variables, formal method parameters, and exception handler parameters are never shared between threads and are unaffected by the memory model.
  • The Java Memory Model defines the behavior of volatile and synchronized, and, more importantly, ensures that a correctly synchronized Java program runs correctly on all processor architectures.
  • The Java Memory Model specifies when the actions of one thread on memory are guaranteed to be visible to another.

The Java Memory Model define the allowed program outcomes by describing what executions are conforming by introducing actions, orders over actions, and consistency rules that govern what actions+orders+constraints constitute a valid execution.

When a the result of a program can be explained by some valid execution, then this result is allowed under Java Memory Model.

Below are the orders and actions under Java Memory Model:
Program order (PO): it defines a total order of actions within each thread. This order provides a connection between the single-threaded execution of the program, and the actions it generates. Executions that have program orders inconsistent with the original programs cannot be used to reason about that particular program’s outcomes.

Synchronization order (SO): it defines a total order over synchronization actions. It comes with two important consistency rules:

  • SO consistency: all reads that come later in the synchronization order see the last write to that location. This property disallows racy results over synchronization actions in conforming executions.
  • SO-PO consistency: the order of synchronization actions in SO within a single thread is consistent with PO in that thread. This means a conforming execution should have the order of SO to agree with PO.

SO consistency and SO-PO consistency mean that in all conforming executions synchronized actions appear sequentially consistent.

Synchronized-with order (SW): a suborder of SO that covers the pairs of synchronization actions that “see? each other. This order serves as the connection bridge between different threads.

Happens-before order (HB): the transitive closure of the union of PO and SW. Unlike SO, HB is a partial order, and only relates some actions, not every pair of actions. Also, unlike SO, HB is able to relate the actions that are not synchronization actions, which allows us to cover all important actions with ordering guarantees. HB comes with the following important consistency rule:

HB consistency: every read can see either the latest write in the happens-before order (notice the symmetry with SO here), or any other write that is not ordered by HB (this allows races).

Causality rules: this is an additional verification on otherwise conforming executions, to rule out causality loops. This is verified by a special process of “committing? the actions from the execution and verifying that no self-justification of actions takes place.

Final field rules: this is tangential to the rest of the model, and describes additional constraints imposed by final fields, e.g. additional happens-before ordering between final field stores and their associated reads.

What is race condition?

A race condition occurs when there are two or more threads accessing and then changing some shared data at the same time, and the final result depends on the timing of how the threads are scheduled.

Because thread scheduling algorithms can swap between threads at any point of time, you don’t know the order in which these threads will attempt to access the shared data.

Its a special condition that occur inside a critical section.

A critical section is a piece of code that is executed by multiple threads concurrently and where the sequence of execution of the threads makes a difference in the result of the concurrent execution of the critical section.

Race conditions may lead to unpredictable outputs and subtle programming bugs.

How to find race condition in java?

Finding Race conditions in any language is a difficult task, since readability of Java code is very good and well constructed to find race conditions by code review.

Finding race conditions by unit testing is not reliable because of random nature of race conditions. There may be the chances that your unit test may passed without facing any race condition.

The best way to find race condition is reviewing code manually or using code review tools which notify you about the race conditions based on code pattern and use of synchronization in Java.

Sometimes doing load testing in production environment may helps to expose race conditions in java.

How to prevent a race condition?

To prevent race condition from occurring you must make sure that the critical section is executed as an atomic instruction.

A thread can prevent this from happening by locking an object.

When an object is locked by one thread and another thread tries to call a synchronized method on the same object, the second thread will block until the object is unlocked.

By proper thread synchronization in critical sections, you can avoid race conditions in your application.

Thread synchronization can be achieved in java by using a synchronized block on your code.

Thread synchronization can also be achieved using other synchronization methods like locks(Re-entrant Lock) or atomic variables like java.util.concurrent.atomic.AtomicInteger.

Threadlocal variable

A single instance of ThreadLocal variable can hold different values of threads separately.

ThreadLocal variables are private to each thread, it means these variables can only be access and written by the same thread.

If two threads are executing inside a process then these two threads can’t see each other’s thread-local variables.

Apart from immutability, ThreadLocal is another way to achieve thread-safety in java.

Methods of threadlocal class:

  • get() : Returns the value in the current thread’s copy of this thread-local variable.
  • initialValue() :Returns the current thread’s "initial value" for this thread-local variable.
  • remove() : Removes the current thread’s value for this thread-local variable.
  • set(T value) : Sets the current thread’s copy of this thread-local variable to the specified value.

Creation of threadlocal variable

ThreadLocal class provides thread-local variables.

private ThreadLocal threadLocal = new ThreadLocal();

This will instantiate a new ThreadLocal object and needs to be done once for each thread.

When two or more threads executes the same code which accesses a ThreadLocal object then each thread will see only its own ThreadLocal instance.

Uses of threadlocal variable

  • ThreadLocal provides wonderful way to implement per thread singleton classes.
  • Wrap any non Thread Safe object in ThreadLocal to make it Thread-safe.
  • A common use of ThreadLocal is seen in DAO pattern where DAO class can be a singleton but database connection can be used separately for each thread.

public class MyThreadLocalExample {
    public static void main(String[] args){
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread, "My Thread-A");
        Thread t2 = new Thread(myThread, "My Thread-B");
class MyThread implements Runnable {
    private ThreadLocal myThreadLocal = new ThreadLocal();
    public void run() {
        try {
        } catch (Exception e) {
        System.out.println(Thread.currentThread().getName() + " : " + myThreadLocal.get());

Why wait() and notify() called from synchronized context?

In simple word we can understand that wait() and notify() methods are called from synchronized because after calling wait() method on object the current thread want to achieve a particular state before executing the block and its only possible if the thread gives signal to other threads via notify() method that the particular state has been achieved and to fulfill this condition the block inside which wait() and notify() methods are calling should be synchronized in nature.


wait() and notify()/notifyAll() methods mostly used for inter-thread communication in Java.

wait() method tells the current thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ) method.

notify() wakes up the first thread that called wait() on the same object. Following problems occurs in java if we do not call wait(), notify() or notifyAll() methods from synchronized context:
1) IllegalMonitorStateException will occur if we don’t call wait(), notify() or notifyAll() method from synchronized context.

2) Race condition between wait() and notify() could exists if we don’t call them inside synchronized method or block.

This race condition is resolved by using synchronized keyword and locking provided by java.

Synchronize your Java object to allow mutual exclusive access of critical section to two threads.

If your code is executing in multi-threaded environment, you need synchronization for objects, which are shared among multiple threads, to avoid any corruption of state or any kind of unexpected behavior.

synchronized keyword in Java provides locking, which ensures mutual exclusive access of shared resource and prevent data race.

Below are the 4 differences between yield() and sleep() method:

  • yield() method temporarily pauses the execution of current thread and allow the execution of remaining waiting threads of the same priority while sleep() method pauses the execution of current thread for specific period of time.
  • yield() method does not provide any guarantee of the pause of current thread, its totally depends upon the priority of thread. If there is no waiting thread or all the waiting threads having lower priority then the same thread will remain in execution while sleep() method provides guarantee to the scheduler that the execution of current thread will pause for specific period of time.
  • yield() method does not provide any guarantee that the current thread will pause but it guarantee that CPU will be relinquished by the current thread while sleep() method does not provide any guarantee that when sleeping thread woke up it will definitely get CPU, instead it will go to Runnable state and fights for CPU with other threads.
  • yield() method does not throws InterruptedException while sleep() method throws InterruptedException if another thread interrupts the sleeping thread.

Use of wait() and notify() in java

  • Both wait() and notify() methods belongs to threads but they are not defined in java.lang.Thread class, instead they are defined in the Object class.
  • Both the methods must called from synchronized context to avoid IllegalMonitorStateException.
  • When the wait() method is called by a thread in Java, then this thread release the lock and go to the wait state. Now this lock is acquired by the other thread who can notify this thread.
  • A thread in wait state due to a call to wait() method can wake up either by calling notify() or notifyAll() methods on the same object or due to interruption.
  • When notify() method is called on a shared object and if more than one thread is waiting on that lock then any thread will get the notification, it is not guaranteed. If only one thread is waiting then it will get the notification.

What is java thread pool?

Java Thread pool is a collection of worker threads that are waiting for the tasks and can be reused many times.

Instead of starting a new thread for every time for each task to execute concurrently, the task can be passed to a existing thread pool.

As soon as the pool has find any idle threads then that task can be assigned to one of them and will be executed.

BlockingQueue is used to implement the thread pool, when a new task is inserted into the queue one of the idle threads will dequeue it successfully and execute it.

The rest of the idle threads in the pool will be blocked and waiting to dequeue tasks.

Example of Thread Pool

Servlets and JSPs are the real time usage of thread pool where container creates a pool of threads to process the incoming request.

Java have built in thread pools in java.util.concurrent package, so there is no need to implement your own thread pool. ExecutorService and Executors interfaces provides many in-built thread pools in java.

ThreadPool is very important in java because it saves time as there is no need to create new thread.

How to check if a thread holds a lock or not?

1. To check if a Thread holds a lock or not we can throw IllegalMonitorStateException. The wait() and notify() methods of Object class require that you hold the lock on the object.

If you do not hold the lock, then these methods will throw IllegalMonitorStateException in this way you can determine whether you hold the lock or not.

If you call wait() or notify() on an object, without explicitly synchronizing, you will find out whether you held the lock on the object.

If you did then the wait() or notify() methods will work and if you did not then IllegalMonitorStateException gets thrown.

2. There is a static method called holdsLock(Object obj) in Thread class which returns true if and only if the current thread holds the monitor lock on the specified object.

What is blocking method in java?

In java blocking methods are those methods which blocks the executing thread until their operation finished.

In most simple way blocking means your code in next line will not be executed because the current thread which is executing blocking method is waiting for some return from that method.

Most of java IO methods are blocking methods and read() method from InputStream class is one the most famous example of blocking method, which blocks until all input data from InputStream has been read completely.

This method blocks until input data is available, an exception is thrown or the end of the stream is detected.

There are many blocking methods present in java APIs and javadoc clearly mention whether a method call is blocking or not.

In most of the case methods related to reading or writing file, reading from socket, opening network connection, updating GUI synchronously uses blocking call. Below are some of the most common methods in java which are blocking in nature: – This method blocks until data is available, end of stream is detected or an exception is thrown.

ServerSocket.accept() – This method listen for incoming socket connection and blocks until a connection is made.

SwingUtilities.invokeAndWait(Runnable r) – This method wait until all pending AWT events get processed and run() method completes.

Other examples of blocking method in java are: wait(), sleep(), join() from multi-threading, put(E e) and take() method from Queue interface are also blocking in nature.

Atomicinteger in java

Definition: AtomicInteger is used primarily in multi-threaded environment when we need to process thread safe operations on an integer value without using synchronized keyword.

Retrieving and assigning operations on primitive type int are already atomic but AtomicInteger provides many other operations which are not atomic. AtomicInteger is a wrapper class for int.

Package: java.util.concurrent.atomic
Since: JDK 1.5

Uses: Two main uses of AtomicInteger :
compareAndSet(int expect, int update)

Beside atomicity AtomicInteger can be used as a mutable version of Integer for instance in Maps as values.

Advantages: AtomicInteger is fast and more readable than synchronization.

What are java synchronizers?

Java Synchronizers are concurrency utilities that provides thread synchronization without using wait() and notify() methods.

The main purpose all the synchronizers is to protect the critical section against concurrent access by multiple thread.

There are five types of Synchronizers present in Java :

  • Semaphore : This synchronizer restrict the number of threads that can access a resource, it means only n threads can access a certain resource at a given time.
  • Countdown LatchCountDown Latch is a synchronizer that allow one or more number of threads to wait until one or more number of threads completed some operation.
  • Cyclic BarrierThis synchronizer allow a set of threads to all wait for each other to reach a common barrier point.
  • Phaser
  • Exchanger

What is deamon thread?

Deamon thread is a low priority thread that runs in background to perform tasks such as garbage collection, they do not prevent the JVM from exiting (even if the daemon thread itself is running) when all the user threads finish their execution.

JVM terminates itself when all user threads finish their execution, JVM does not care whether daemon thread is running or not. If JVM finds running daemon thread (upon completion of user threads), it terminates the thread and after that shutdown itself.

Properties of daemon threads:

A newly created thread inherits the daemon status of its parent. That’s the reason all threads created inside main method (child threads of main thread) are non-daemon by default, because main thread is non-daemon.

However you can make a user thread to Daemon thread by using setDaemon() method of Thread class.

When the JVM starts, it creates a thread called “Main?. Your program will run on this thread, unless you create additional threads yourself.

The first thing the “Main? thread does is to look for your static void main (String args[]) method and invoke it. That is the entry-point to your program.

If you create additional threads in the main method those threads would be the child threads of main thread.

Methods of thread class that are related to daemon threads:

1. public void setDaemon(boolean status): This method is used for making a user thread to Daemon thread or vice versa.

For example if I have a user thread t then t.setDaemon(true) would make it Daemon thread. On the other hand if I have a Daemon thread td then by calling td.setDaemon(false) would make it normal thread(user thread/non-daemon thread).

public boolean isDaemon(): This method is used for checking the status of a thread. It returns true if the thread is Daemon else it returns false.

2. setDaemon() method can only be called before starting the thread. This method would throw IllegalThreadStateException if you call this method after Thread.start() method.

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions
  • Vinod
    Hi karthik
    Thanks for beautiful explanation it's really good tutorial. 
    Could you please provide more details on framework using POM and sample working Framework code. 
    Thanks in advance