Multithreading

Multithreading refers to two or more tasks executing concurrently within a single program. A thread is an independent path of execution within a program. Many threads can run concurrently within a program. Every thread in Java is created and controlled by the java.lang.Thread class. A Java program can have many threads, and these threads can run concurrently, either asynchronously or synchronously.

Multithreading has several advantages over Multiprocessing such as;

  • Threads are lightweight compared to processes
  • Threads share the same address space and therefore can share both data and code
  • Context switching between threads is usually less expensive than between processes
  • Cost of thread intercommunication is relatively low that that of process intercommunication
  • Threads allow different tasks to be performed concurrently.

The following figure shows the methods that are members of the Object and Thread Class.

object thread

Why are wait(), notify() and notifyAll() methods defined in the object class?

Ans: The purpose of the wait(), notify() and notifyAll() methods is to temporarily pause and resume the execution of code in an object. Typically the host object is not in a state where it can proceed with a method call it has been given and the thread of execution must literally wait for the object to return to a ready state. A common example would be a limited pool or store of objects where you must wait for a storage slot to be released or an object to be returned to the pool before you can use it.

public synchronized Object getNextObject() {
// Waiting loop

while (! objectAvailable()) {

try {

wait();

}

catch (InterruptedException e) {

// Handle exception

}

}


// No longer waiting, get the return object

Object returnObject;

// Assign the returnObject from store

/ Notify state change for other waiters

notify();
return returnObject;

}

The act of waiting is associated with the Object class because any subclass may need to wait for a ready state to occur (Java is fundamentally a multi-threaded language). The waiting process acts on a single thread of execution, but the wait mechanism expects that multiple threads may be waiting for the same object. The wait() and notify() methods are hosted by the Object class so that the Java Virtual Machine can manage the “wait set” of threads through the objects they are waiting for.


Advantage of Java Multithreading

  • Itdoesn’t block the user because threads are independent and you can perform multiple operations at same time.
  • Youcan perform many operations together so it saves time.
  • Threads areindependent so it doesn’t affect other threads if exception occur in a single thread.

Multitasking

Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking can be achieved by two ways:

  • Process-based Multitasking(Multiprocessing)
  • Thread-based Multitasking(Multithreading)

1) Process-based Multitasking (Multiprocessing)

  • Each process have its own address in memory i.e. each process allocates separate memory area.
  • Process is heavyweight.
  • Cost of communication between the process is high.
  • Switching from one process to another require some time for saving and loading registers, memory maps, updating lists etc.

2) Thread-based Multitasking (Multithreading)

  • Threads share the same address space.
  • Thread is lightweight.
  • Cost of communication between the thread is low.

Note: At least one process is required for each thread.


Difference between multithreading and multi-tasking

1) In multitasking, several programs are executed concurrently e.g. Java compiler and a Java IDE like Netbeans or Eclipse, while in multi-threading multiple threads execute either same or different part of program multiple times at the same time.
2) Multi-threading is more granular than multi-tasking. In multi-tasking,  CPU switches between multiple programs to complete their execution in real time, while in multi-threading CPU switches between multiple threads of the same program. Remember, switching between multiple processes has more context switching cost than switching between multiple threads of the same program.
3) Process are heavyweight as compared to threads, they require their own address space, which means multi-tasking is heavy compared to multithreading. Inter-process communication is expensive and limited and context switching from one process to another is expensive and limited.  Seedifference between a Process and a Thread to learn more.

Here is the summary of difference between multitasking and multithreading in concurrent programming:
diff threading and tasking

That’s all about the difference between multitasking and multithreading. Both are used to parallelize things in order to take full advantage of expensive hardware and CPU.  Multitasking is an ability of a computer to execute multiple programs at the same time while multi-threading is the ability of a process to execute multiple threads at the same time.  Sometimes multitasking is useful and other time multi-threading.


Life cycle of a Thread

thread lyfcycle

  1. New :A thread begins its life cycle in the new state. It remains in this state until the start() method is called on it.
  2. Runable :After invocation of start() method on new thread, the thread becomes runable.
  3. Running :A method is in running thread if the thread scheduler has selected it.
  4. Waiting :A thread is waiting for another thread to perform a task. In this stage the thread is still alive.
  5. Terminated :A thread enter the terminated state when it complete its task.

Thread Priorities

Every thread has a priority that helps the operating system determine the order in which threads are scheduled for execution. In java thread priority ranges between,

  • MIN-PRIORITY (a constant of 1)
  • MAX-PRIORITY (a constant of 10)

By default every thread is given a NORM-PRIORITY(5). The main thread always have NORM-PRIORITY.


How to create thread

There are two ways to create a thread:

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

Thread Class

Thread class is the main class on which Java’s Multithreading system is based. Thread class, along with its companion interface Runnable will be used to create and run threads for utilizing Multithreading feature of Java.

Constructors of Thread class

  1. Thread( )
  2. ThreadString str )
  3. ThreadRunnable r )
  4. ThreadRunnable rString str)

You can create new thread, either by extending Thread class or by implementing Runnable interface. Thread class also defines many methods for managing threads. Some of them are,

Method Description
setName() to give thread a name
getName() return thread’s name
getPriority() return thread’s priority
isAlive() checks if thread is still running or not
join() Wait for a thread to end
run() Entry point for a thread
sleep() suspend thread for a specified time
start() start a thread by calling run() method

Some Important points to Remember

  1. When we extend Thread class, we cannot override setName() and getName() functions, because they are declared final in Thread class.
  2. While usingsleep(), always handle the exception it throws.

static void sleep(long milliseconds) throws InterruptedException

class MyThread extends Thread{
 public void run() {
  System.out.println("Concurrent thread started running..");
 }
}
classMyThreadDemo{
 public static void main( String args[] ) {
  MyThread mt = new  MyThread();
  mt.start();
 }
}
Output :
concurrent thread started running..
In this case also, as we must override the run() and then use the start() method to start and run the thread. Also, when you create MyThread class object, Thread class constructor will also be invoked, as it is the super class, hence MyThread class object acts as Thread class object.

Implementing the Runnable Interface

The easiest way to create a thread is to create a class that implements the runnable interface. After implementing runnable interface , the class needs to implement the run() method, which is of form,

public void run()

  • run() method introduces a concurrent thread into your program. This thread will end when run() returns.
  • You must specify the code for your thread inside run() method.
  • run() method can call other methods, can use other classes and declare variables just like any other normal method.

 

class MyThread implements Runnable{
 public void run() {
  System.out.println("concurrent thread started running..");
 }
}
class MyThreadDemo{
 public static void main( String args[] ) {
  MyThread mt = new MyThread();
  Thread t = new Thread(mt);
  t.start();
 }
}
Output :
concurrent thread started running..

To call the run() method, start() method is used. On calling start(), a new stack is provided to the thread and run() method is called to introduce the new thread into the program.


Types Of Threads In Java

There are two types of Threads in java.

  • User Thread
  • Daemon Thread

1) User Thread :

User threads are threads which are created by the application or user. They are high priority threads. JVM (Java Virtual Machine) will not exit until all user threads finish their execution. JVM wait for these threads to finish their task. These threads are foreground threads.

2)Daemon Thread :

Daemon threads are threads which are mostly created by the JVM. These threads always run in background. These threads are used to perform some background tasks like garbage collection and house-keeping tasks. These threads are less priority threads. JVM will not wait for these threads to finish their execution. JVM will exit as soon as all user threads finish their execution. JVM doesn’t wait for daemon threads to finish their task.


Some Things-To-Remember about user threads and daemon threads In Java :

o	You can convert user thread into daemon thread explicitly by calling setDaemon() method of the thread.

class UserThread extends Thread
{
    @Override
    public void run()
    {
        for(int i = 0; i < 1000; i++)
        {
            System.out.println("This is an user thread....");
        }
    }
}
 
public class ThreadsInJava
{
    //Main Thread
    public static void main(String[] args)
    {
        UserThread userThread = new UserThread();   //Creating the UserThread
 
        userThread.setDaemon(true);        //Changing the thread as Daemon
 
        userThread.start();               //Starting the thread
    }
}
o	You can’t set a daemon property after starting the thread. If you try to set the daemon property when the thread is active, It will throw a IllegalThreadStateException at run time.

class UserThread extends Thread
{
    @Override
    public void run()
    {
        for(int i = 0; i < 1000; i++)
        {
            System.out.println("This is an user thread....");
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        UserThread userThread = new UserThread();   //Creating the UserThread
 
        userThread.start();               //Starting the thread
 
        userThread.setDaemon(true);        //This statement will throw IllegalThreadStateException
    }
}

o	You can check whether the thread is user thread or a daemon thread by using isDaemon() method of Thread class. This method returns “true” for a daemon thread and “false” for a user thread.

class UserThread extends Thread
{
    @Override
    public void run()
    {
        for(int i = 0; i < 1000; i++)
        {
            System.out.println("This is an user thread....");
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        UserThread userThread = new UserThread();   //Creating the UserThread
 
        System.out.println(userThread.isDaemon());    //Output : false
 
        userThread.setDaemon(true);         //changing the thread as Daemon
 
        userThread.start();                 //Starting the thread
 
        System.out.println(userThread.isDaemon());      //Output : true
    }
}

o	Daemon property of a thread is inherited from it’s parent thread. i.e The thread created by user thread will be user thread and the thread created by daemon thread will be a daemon thread.

class Thread1 extends Thread
{
    @Override
    public void run()
    {
        Thread t = new Thread();      //Creating a child thread
 
        System.out.println(t.isDaemon());   //Checking the Daemon property of a child thread
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread1 t1 = new Thread1();   //Creating the Thread1
 
        t1.start();                 //Starting the thread
 
        Thread1 t2 = new Thread1();   //Creating the Thread1
 
        t2.setDaemon(true);         //changing the thread as Daemon
 
        t2.start();          //Starting the thread
    }
}

o	The main thread or primary thread created by JVM is an user thread.
o	Demonstration of User thread and daemon thread  :  In the below program, The task of daemon thread will not be completed. Program terminates as soon as user thread finishes it’s task. It will not wait for daemon thread to finish it’s task.

class UserThread extends Thread
{
    @Override
    public void run()
    {
        System.out.println("This is a user thread.....");
    }
}
 
class DaemonThread extends Thread
{
    public DaemonThread()
    {
        setDaemon(true);
    }
 
    @Override
    public void run()
    {
        for(int i = 0; i < 1000; i++)
        {
            System.out.println("This is daemon thread....."+i);
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        DaemonThread daemon = new DaemonThread();   //Creating the DaemonThread
 
        daemon.start();                 //Starting the daemon thread
 
        UserThread userThread = new UserThread();   //Creating the UserThread
 
        userThread.start();          //Starting the user thread
    }
}



Naming A Thread In Java

You can give a name to a thread by using setName() method of Thread class. You can also retrieve the name of a thread using getName() method of a Thread class. These two methods are public and final. Below is the method signatures of these methods.

  • 1)  public final void setName(String name) —-> It changes the name of the thread to “name”.
  • 2)  public final String getName() —-> Returns the name of the thread.

Below example shows how to use setName() and getName() methods.

class MyThread extends Thread
{
    @Override
    public void run()
    {
        System.out.println("Keep some task here....");
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        MyThread thread = new MyThread();     //Creating a thread
 
        thread.start();                     //Starting a thread
 
        thread.setName("My Thread");        //Giving a name to the thread
 
        String name = thread.getName();    //Retreiveing the name of the thread
 
        System.out.println(name);   //Output : My Thread
    }
}


Some Things-To-Remember about Naming a thread in java :

  • setName() method may throw a SecurityException at run time if the current thread can not modify the name of the specified thread.
  • You can change the name of a thread at any state of the thread.
class MyThread extends Thread
{
    @Override
    public void run()
    {
        for(int i = 0; i < 1000; i++)
        {
            System.out.println(i);
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        MyThread thread = new MyThread();     
 
        thread.setName("My Thread");        //Changing the name of the thread before starting the thread
 
        thread.start();                     
 
        thread.setName("My Thread");        //changing the name of the thread when thread is active
 
        try
        {
            thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        thread.setName("My Thread");     //Changing the name of the thread when thread is sleeping
    }
}


o	Default Name Of The Thread :
In Java, All threads have names. If you are not providing the name to a thread, thread will get default name. Default name of the thread will be consist of a word “Thread”, followed by hyphen (-) and followed by an integer number starting with 0.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread t = new Thread();
 
        System.out.println(t.getName());    //Output : Thread-0
    }
}

o	How to retrieve a name of the primary thread or main thread?
First, get the reference of the main thread by using currentThread() method of Thread class. currentThread() method returns the reference of currently executing thread. After, getting the reference of the main thread, use the getName() method to retrieve the name of the thread.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName());    //Output : main
    }
}

o	Can we change the name of the main thread ?
Yes, we can change the name of the main thread. It can be done by first getting the reference of the main thread by using currentThread() method and then calling setName() method on it.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread t = Thread.currentThread();
 
        t.setName("main-thread-name-modified");
 
        System.out.println(t.getName());    //Output : main-thread-name-modified
    }
}

o	Another method of naming a thread in java :
You can pass name of the thread while creating the object to thread. There is a constructor in Thread class which takes name of the thread as an argument.

class MyThread extends Thread
{
    public MyThread(String name)
    {
        super(name);
    }
 
    @Override
    public void run()
    {
        System.out.println(getName());      //Output : My Thread
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        MyThread t = new MyThread("My Thread");    //passing the name while creating the thread
 
        t.start();
    }
}

o	Naming a thread is very useful in identifying a thread and also in debugging a code.


Joining The Threads In Java

The join() method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task.

join() method of java.lang.Thread class is used to mantain the order of execution of threads. Using join() method, you can make the currently executing thread to wait for the some other threads to finish their task. For example, Let’s us assume that there are two threads namely, thread1 and thread2. You can make thread1 to hold it’s execution for some time so that thread2 can finish it’s task. After, thread2 finishes it’s task, thread1 resumes it’s execution.For this to happen, you should call join() method on thread2 within thread1.

Like sleep() method, join() method is also overloaded in Thread class. There are three forms of join() method available in Thread class.

1) public final void join() throws InterruptedException

—> Currently executing thread waits for a thread to finish it’s task on which it is called.

2) public final void join(long millis) throws InterruptedException

—> currently executing thread waits at most millis milliseconds for a thread to finish it’s task on which it is called.

3) public final void join(long millis, int nanos) throws InterruptedException

—> Currently executing thread waits at most millis milliseconds plus nanos nanoseconds for a thread to finish it’s task on which it is called.

Like sleep() method, join() method also throws InterruptedException. Therefore, you have to keep calling statement to join() method in try-catch blocks or else propagate the exception with throws clause.

The below example shows usage of all these three forms of join() method.

public class ThreadsInJava
{
    public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main thread started : Task is to print numbers from 0 to 3000");
 
        final Thread t1 = new Thread()
        {
            @Override
            public void run()
            {
                //Thread t1 started : Task is to print numbers from 0 to 1000"
 
                for(int i = 0; i <= 1000; i++)
                {
                    System.out.println(i);
                }
 
                System.out.println("Numbers from 0 to 1000 are printed");
            }
        };
 
        final Thread t2 = new Thread()
        {
            @Override
            public void run()
            {
                //Thread t2 started : Task is to print numbers from 1001 to 2000
 
                try
                {
                    t1.join(5000, 500000);   //waits at most 5.5 seconds for thread t1 to finish it's task
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
 
                for(int i = 1001; i <= 2000; i++)
                {
                    System.out.println(i);
                }
 
                System.out.println("Numbers from 1001 to 2000 are printed");
            }
        };
 
        Thread t3 = new Thread()
        {
            @Override
            public void run()
            {
                //Thread t3 started : Task is to print numbers from 2001 to 3000
 
                try
                {
                    t2.join(5000);   //waits at most 5 seconds for thread t2 to finish it's task
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
 
                for(int i = 2001; i <= 3000; i++)
                {
                    System.out.println(i);
                }
 
                System.out.println("Numbers from 2001 to 3000 are printed");
            }
        };
 
        t3.start();
 
        t2.start();
 
        t1.start();
 
        t3.join();     //Waits for t3 thread to finish it's task
 
        //No need enclose this join statement in try-catch blocks as we have already specified the exception with throws clause.
 
        System.out.println("Task is finished");
    }
}

The main task of above example is to print the numbers from 0 to 3000. This task is divided into three parts and each part is assigned to one thread. i.e The task of printing the numbers from 0 to 1000 is assigned to thread t1, printing the numbers from 1001 to 2000 is assigned to thread t2 and printing the numbers from 2001 to 3000 is assigned to thread t3.The main thread creates and starts these three threads. main thread also calls join method on thread t3 (Line 79). So main thread waits until thread t3 finishes its task. Before starting it’s task, thread t3 calls join method on thread t2 (Line 57). So, thread t3 waits at most 5 seconds for thread t2 to finish it’s task. Thread t2 also calls join method on thread t1 (Line 32). So, thread t2 waits at most 5.5 seconds for thread t1 to finish it’s task. So, first t1 finishes its task and then t2 finishes its task and after that t3 finishes its task. After all these three threads finish their task, main threads complete the task.


Thread.sleep() Method In Java

Thread.sleep() method makes the currently executing thread to pause it’s execution for a specified period of time. There are two overloaded forms of sleep() method available in java.lang.Thread class. They are,

1) public static void sleep(long millis) throws InterruptedException

—> It causes the currently executing thread to sleep for specified number of milliseconds.

2) public static void sleep(long millis, int nanos) throws InterruptedException

—> It makes the currently executing thread to sleep for specified number of milliseconds plus specified number of nanoseconds.

Thread.sleep() method throws InterruptedException if a thread in sleep is interrupted by other threads. InterruptedException is a checked type of exception. That means, “Thread.sleep()” statement must be enclosed within try-catch blocks or it must be specified with throws clause.

The following example shows how to use Thread.sleep() method.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        System.out.println("Before Sleeping");
 
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        System.out.println("After Sleeping");
    }
}

In the above example, the main thread first prints “Before Sleeping”. After that it pauses for 5000 milisseconds(5 seconds) and prints “After Sleeping”. Notice that the statement “Thread.sleep(5000)” is enclosed within try-catch blocks.
Some Things-To-Remember About Thread.sleep() Method In Java :
o	It is always current thread that is going to sleep. For example, In the below example, main thread is going to sleep not “My Thread” even though you are calling sleep() method on “My Thread”.

class MyThread extends Thread
{
    public MyThread(String name)
    {
        super(name);
    }
 
    @Override
    public void run()
    {
        for(int i = 0; i <= 1000; i++)
        {
            System.out.println(i);
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        MyThread thread = new MyThread("My Thread");
 
        thread.start(); 
 
        System.out.println("Before Sleeping");
 
        try
        {
            thread.sleep(5000);       //main thread is going for sleep not My Thread
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        System.out.println("After Sleeping");
    }
}
o	It is a bad practice to call sleep() method with an instance of Thread class as in the above example. If you want a particular thread to sleep for a while, then call sleep() method inside the run() method of that thread.

class MyThread extends Thread
{
    @Override
    public void run()
    {
        for(int i = 0; i <= 10; i++)
        {
            System.out.println(i);
 
            try
            {
                sleep(1000);            //this thread sleeps for 1 second
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        MyThread thread = new MyThread();
 
        thread.start();
    }
}

o	An example for using second form of sleep() method.

public class ThreadsInJava{
    public static void main(String[] args)
    {
        System.out.println("Before Sleeping");
 
        try
        {
            Thread.sleep(5000, 500000);       //thread sleeps for about 5.5 seconds
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        System.out.println("After Sleeping");
    }
}

o	Thread.sleep() method may also throws IllegalArgumentException if miilis value is negative or nanos value is not in the range 0 – 999999.

public class ThreadsInJava{
    public static void main(String[] args)    {
        System.out.println("Before Sleeping");
 
        try        {
            Thread.sleep(-5000);          //This statement throws IllegalArgumentException
        }
        catch (Exception e)        {
            e.printStackTrace();
        }
 
        System.out.println("In between sleep");
 
        try        {
            Thread.sleep(1000, 50000000);       //This statement throws IllegalArgumentException
        }
        catch (Exception e)        {
            e.printStackTrace();
        }
 
        System.out.println("After Sleeping");
    }
}

o	When the thread is going for sleep, it does not release the synchronized locks it holds.

Daemon Thread in Java

Daemon thread in java is a service provider thread that provides services to the user thread. Its life depend on the mercy of user threads i.e. when all the user threads dies, JVM terminates this thread automatically.

There are many java daemon threads running automatically e.g. gc, finalizer etc.

You can see all the detail by typing the jconsole in the command prompt. The jconsole tool provides information about the loaded classes, memory usage, running threads etc.

Points to remember for Daemon Thread in Java

  • It provides services to user threads for background supporting tasks. It has no role in life than to serve user threads.
  • Its life depends on user threads.
  • It is a low priority thread.

Why JVM terminates the daemon thread if there is no user thread?

The sole purpose of the daemon thread is that it provides services to user thread for background supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM terminates the daemon thread if there is no user thread.

Methods for Java Daemon thread by Thread class

The java.lang.Thread class provides two methods for java daemon thread.

No. Method Description
1) public void setDaemon(boolean status) is used to mark the current thread as daemon thread or user thread.
2) public boolean isDaemon() is used to check that current is daemon.
Simple example of Daemon thread in java
File: MyThread.java
public class TestDaemonThread1 extends Thread{  
 public void run(){  
  if(Thread.currentThread().isDaemon()){//checking for daemon thread  
   System.out.println("daemon thread work");  
  }  
  else{  
  System.out.println("user thread work");  
 }  
 }  
 public static void main(String[] args){  
  TestDaemonThread1 t1=new TestDaemonThread1();//creating thread  
  TestDaemonThread1 t2=new TestDaemonThread1();  
  TestDaemonThread1 t3=new TestDaemonThread1();  
    t1.setDaemon(true);//now t1 is daemon thread  
      t1.start();//starting threads  
  t2.start();  
  t3.start();  
 }  
}  
Test it Now
Output
daemon thread work
user thread work
user thread work

Synchronization

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.

Every Java object with a critical section of code gets a lock associated with the object. To enter critical section a thread need to obtain the corresponding object’s lock.

General Syntax :

synchronized (object){

//statement to be synchronized

}


Why we use Syncronization ?

If we do not use syncronization, and let two or more threads access a shared resource at the same time, it will lead to distorted results.

Consider an example, Suppose we have two different threads T1 and T2, T1 starts execution and save certain values in a file temporary.txt which will be used to calculate some result when T1 returns. Meanwhile, T2 starts and before T1 returns, T2 change the values saved by T1 in the file temporary.txt (temporary.txt is the shared resource). Now obviously T1 will return wrong result.

To prevent such problems, synchronization was introduced. With synchronization in above case, once T1 starts using temporary.txt file, this file will be locked(LOCK mode), and no other thread will be able to access or modify it until T1 returns.


Using Synchronized Methods

Using Synchronized methods is a way to accomplish synchronization. But lets first see what happens when we do not use synchronization in our program.

 

Example with no Synchronization
class First{
 public void display(String msg) {
  System.out.print ("["+msg);
  try  {
   Thread.sleep(1000); 
  }
  catch(InterruptedException e)  {
   e.printStackTrace();
  }
  System.out.println ("]");
 }
}
class Second extends Thread{
 String msg;
 First fobj;
 Second (First fp,String str) {
  fobj = fp;
  msg = str;
  start();
 }
 public void run() {
  fobj.display(msg);
 }
}
public class Syncro{
 public static void main (String[] args)  {
  First fnew = new First();
  Second ss = new second(fnew, "welcome");
  Second ss1= new second (fnew,"new");
  Second ss2 = new second(fnew, "programmer");
 }
}
Output :
[welcome [ new [ programmer]]]
In the above program, object fnew of class First is shared by all the three running threads(ss, ss1 and ss2) to call the shared method(void display). Hence the result is unsynchronized and such situation is called Race condition.

Synchronized Keyword

To synchronize above program, we must serialize access to the shared display() method, making it available to only one thread at a time. This is done by using keyword synchronized with display() method.

synchronized void display (String msg)


Using Synchronised block

If you have to synchronize access to object of a class that has no synchronized methods, and you cannot modify the code. You can use synchronized block to use it.

class First{
 public void display(String msg) {
  System.out.print ("["+msg);
  try  {
   Thread.sleep(1000);
  }
  catch(InterruptedException e)  {
   e.printStackTrace();
  }
  System.out.println ("]");
 }
}
class Second extends Thread{
 String msg;  
 First fobj;
 Second (First fp,String str) {
  fobj = fp;
  msg = str;
  start();
 }
 public void run() {
  synchronized(fobj)        {//Synchronized block
   fobj.display(msg);
  }
 }}
public class Syncro{
 public static void main (String[] args)  {
  First fnew = new First();
  Second ss = new second(fnew, "welcome");
  Second ss1= new second (fnew,"new");
  Second ss2 = new second(fnew, "programmer");
 }
}
Output :
[welcome] 
[new]
[programmer]
Because of synchronized block this program gives the expected output.

Synchronization in java is a strategy or a method to avoid thread interference and hence protecting the data from inconsistency. synchronization is also one of the way to make code thread safe. Through synchronization, we can make the threads to execute particular method or block in sync not simultaneously.

Synchronization in java is implemented using synchronized keyword. synchronized keyword can be used with methods or blocks but not with the variables.

When a method or block is declared as synchronized, only one thread can enter into that method or block. When one thread is executing synchronized method or block, the other threads which wants to execute that method or block wait or suspend their execution until first thread is done with that method or block. Thus avoiding the thread interference and achieving thread safeness. This can be explained well with the help of an example.

class Shared
{
    int i;
 
    synchronized void SharedMethod()
    {
        Thread t = Thread.currentThread();
 
        for(i = 0; i <= 1000; i++)
        {
            System.out.println(t.getName()+" : "+i);
        }
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        final Shared s1 = new Shared();
 
        Thread t1 = new Thread("Thread - 1")
        {
            @Override
            public void run()
            {
                s1.SharedMethod();
            }
        };
 
        Thread t2 = new Thread("Thread - 2")
        {
            @Override
            public void run()
            {
                s1.SharedMethod();
            }
        };
 
        t1.start();
 
        t2.start();
    }
}
In the above example, both threads t1 and t2 wants to execute sharedMethod() of s1 object. But, sharedMethod() is declared as synchronized. So, whichever thread enters first into sharedMethod(), it continues to execute that method. The other thread waits for first thread to finish it’s execution of sharedMethod(). It never enters into sharedMethod() until first thread is done with that method. That means, both threads are executing sharedMethod() one by one not simultaneously. This protects the value of “i” in the memory for a particular thread.

The Logic Behind The Synchronization In Java :

The synchronization in java is built around an entity called object lock or monitor. Here is the brief description about lock or monitor.

  • Whenever an object is created to any class, an object lock is created and is stored inside the object.
  • One object will have only one object lock associated with it.
  • Any thread wants to enter into synchronized methods or blocks of any object, they must acquire object lock associated with that object and release the lock after they are done with the execution.
  • The other threads which wants to enter into synchronized methods of that object have to wait until the currently executing thread releases the object lock.
  • To enter into static synchronized methods or blocks, threads have to acquire class lock associated with that class as static members are stored inside the class memory.

Synchronized Blocks :

Some times, you need only some part of the method to be synchronized not the whole method. This can be achieved with synchronized blocks. Synchronized blocks must be defined inside a definition blocks like methods, constructors, static initializer or instance initializer.

synchronized block takes one argument and it is called mutex. if synchronized block is defined inside non-static definition blocks like non-static methods, instance initializer or constructors, then this mutex must be an instance of that class. If synchronized block is defined inside static definition blocks like static methods or static initializer, then this mutex must be like ClassName.class.

 

 

Here is an example of static and non-static synchronized blocks.
class Shared{
    static void staticMethod()    {
        synchronized (Shared.class)        {
            //static synchronized block
        }
    }
 
    void NonStaticMethod()    {
        synchronized (this)        {
            //Non-static synchronized block
        }
    }
 
    void anotherNonStaticMethod()    {
        synchronized (new Shared())        {
            //Non-static synchronized block
        }
    }
}

10 Points-To-Remember About Synchronization In Java :

1) You can use synchronized keyword only with methods but not with variables, constructors, static initializer and instance initializers.


class Shared{
    synchronized int i;    //compile time error, can't use synchronized keyword with variables
 
    synchronized public Shared()    {
        //compile time error, constructors can not be synchronized
    }
 
    synchronized static    {
        //Compile time error, Static initializer can not be synchronized
    }
 
    synchronized    {
        //Compile time error, Instance initializer can not be synchronized
    }
}

2) Constructors, Static initializer and instance initializer can’t be declared with synchronized keyword, but they can contain synchronized blocks.
class Shared{
    public Shared()    {
        synchronized (this)        {
            //synchronized block inside a constructor
        }
    }
 
    static    {
        synchronized (Shared.class)        {
            //synchronized block inside a static initializer
        }
    }
 
    {
        synchronized (this)        {
            //synchronized block inside a instance initializer
        }
    }
}

3) Both static and non-static methods can use synchronized keyword. For static methods, thread need class level lock and for non-static methods, thread need object level lock.
lass Shared{
    synchronized static void staticMethod()    {
        //static synchronized method
    }
 
    synchronized void NonStaticMethod()    {
        //Non-static Synchronized method
    }
}

4) It is possible that both static synchronized and non-static synchronized methods can run simultaneously. Because, static methods need class level lock and non-static methods need object level lock.
5) A method can contain any number of synchronized blocks. This is like synchronizing multiple parts of a method.
class Shared{
    static void staticMethod()    {
        synchronized (Shared.class)        {
            //static synchronized block - 1
        }
 
        synchronized (Shared.class)        {
            //static synchronized block - 2
        }
    }
 
    void NonStaticMethod()    {
        synchronized (this)        {
            //Non-static Synchronized block - 1
        }
 
        synchronized (this)        {
            //Non-static Synchronized block - 2
        }
    }
}
6) Synchronization blocks can be nested.
synchronized (this){
    synchronized (this)    {
        //Nested synchronized blocks
    }
}

7) Lock acquired by the thread before executing a synchronized method or block must be released after the completion of execution, no matter whether execution is completed normally or abnormally (due to exceptions).
8) Synchronization in java is Re-entrant in nature. A thread can not acquire a lock that is owned by another thread. But, a thread can acquire a lock that it already owns. That means if a synchronized method gives a call to another synchronized method which needs same lock, then currently executing thread can directly enter into that method or block without acquiring the lock.
9) synchronized method or block is very slow. They decrease the performance of an application. So, special care need to be taken while using synchronization. Use synchronization only when you needed it the most.
10) Use synchronized blocks instead of synchronized methods. Because, synchronizing some part of a method improves the performance than synchronizing the whole method.

Deadlock In Java

Deadlock in java is a part of multithreading. Deadlock can occur in a situation when a thread is waiting for an object lock, that is acquired by another thread and second thread is waiting for an object lock that is acquired by first thread. Since, both threads are waiting for each other to release the lock, the condition is called deadlock.

Deadlock in java is a condition which occurs when two or more threads get blocked waiting for each other for an infinite period of time to release the resources(Locks) they hold. Deadlock is the common problem in multi threaded programming which can completely stops the execution of an application. So, extra care need to be taken while writing the multi threaded programs so that deadlock never occurs.

Let’s look at one simple example of deadlock condition.

class Shared{
    synchronized void methodOne(Shared s)    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName()+"is executing methodOne...");
 
        System.out.println(t.getName()+"is calling methodTwo...");
 
        s.methodTwo(this);
 
        System.out.println(t.getName()+"is finished executing methodOne...");
    }
 
    synchronized void methodTwo(Shared s)    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName()+"is executing methodTwo...");
 
        System.out.println(t.getName()+"is calling methodOne...");
 
        s.methodOne(this);
 
        System.out.println(t.getName()+"is finished executing methodTwo...");
    }
}
 
public class DeadLockInJava{
    public static void main(String[] args)    {
        final Shared s1 = new Shared();
 
        final Shared s2 = new Shared();
 
        Thread t1 = new Thread()        {
            public void run()            {
                s1.methodOne(s2);
            }
        };
 
        Thread t2 = new Thread()        {
            @Override
            public void run()            {
                s2.methodTwo(s1);
            }
        };
 
        t1.start();
 
        t2.start();
    }
}

In the above multithreaded program, thread t1 and t2 are concurrent threads i.e they are executing their task simultaneously. There are two Shared class objects, s1 and s2, which are shared by both the threads. Shared class has two synchronized methods, methodOne() and methodTwo(). That means, only one thread can execute these methods at a given time.

First, thread t1 enters the methodOne() of s1 object by acquiring the object lock of s1. At the same time, thread t2 also enters the methodTwo() of s2 object by acquiring the object lock of s2methodOne() of s1 object, currently executing by thread t1, calls methodTwo() of s2 object from it’s body. So, thead t1 tries to acquire the object lock of s2 object. But object lock of s2 object is already acquired by thread t2. So, thread t1 waits for thread t2 to release the object lock of s2object.

At the same time, thread t2 is also executing methodTwo() of s2 object. methodTwo() of s2 object also makes a call tomethodOne() of s1 object. So, thread t2 tries to acquire the object lock of s1 object. But, it is already acquired by threadt1. So, thread t2 also waits for thread t1 to release the object lock of s1 object.

Thus, both the threads wait for each other to release the object locks they own. They wait for infinite period of time to get the object locks owned by opposite threads. This condition of threads waiting forever is called Deadlock.

How To Detect The Deadlocked Threads In Java

In the previous article, we have seen what is the deadlock and why it occurs. Deadlock is the condition which occurs when two or more threads wait for each other forever.

Programmatically, You can detect the threads which have entered into deadlock condition and also you can retrieve the details about them. This can be done using ThreadMXBean interface of java.lang.Management package. You can go through the oracle docs of ThreadMXBean interface here.

First, you have to get an instance of ThreadMXBean using getThreadMXBean() method of ManagementFactory, like this.

ThreadMXBean bean = ManagementFactory.getThreadMXBean();

After getting an instance of ThreadMXBean, call findMonitorDeadlockedThreads() method on it. It returns an array of type long containing ids of all currently deadlocked threads.

long ids[] = bean.findMonitorDeadlockedThreads();

After getting the ids of deadlocked threads, pass these ids to getThreadInfo() method of ThreadMXBean. It will return an array of ThreadInfo objects, where one ThreadInfo object contains the details of one deadlocked thread.

ThreadInfo threadInfo[] = bean.getThreadInfo(ids);

Iterate the ThreadInfo array to get the details of individual deadlocked thread.

  for (ThreadInfo threadInfo1 : threadInfo){

System.out.println(threadInfo1.getThreadName());    //Prints the name of deadlocked thread

}

Here are the some methods of ThreadInfo class which are useful to retrieve the details of deadlocked threads.

getThreadId()               —>    Returns the ID of a deadlocked thread.

getThreadName()         —>     Returns the name of a deadlocked thread.

getBlockedTime()          —>    Returns the elapsed time in milli seconds that a thread is in deadlock condition.

getLockName()             —>    Returns string representation of an object for which thread has been waiting.

getLockOwnerId()         —>    Returns ID of a thread that currently owns the object lock.

getLockOwnerName()    —>    Returns the name of a thread that currently owns the object lock.

Here is  example that has been modified to get the details of deadlocked threads.
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
 
class Shared
{
    synchronized void methodOne(Shared s)
    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName()+"is executing methodOne...");
 
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        System.out.println(t.getName()+"is calling methodTwo...");
 
        s.methodTwo(this);
 
        System.out.println(t.getName()+"is finished executing methodOne...");
    }
 
    synchronized void methodTwo(Shared s)
    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName()+"is executing methodTwo...");
 
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        System.out.println(t.getName()+"is calling methodOne...");
 
        s.methodOne(this);
 
        System.out.println(t.getName()+"is finished executing methodTwo...");
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        final Shared s1 = new Shared();
 
        final Shared s2 = new Shared();
 
        Thread t1 = new Thread()
        {
            public void run()
            {
                s1.methodOne(s2);
            }
        };
 
        Thread t2 = new Thread()
        {
            @Override
            public void run()
            {
                s2.methodTwo(s1);
            }
        };
 
        t1.start();
 
        t2.start();
 
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        ThreadMXBean bean = ManagementFactory.getThreadMXBean();
 
        long ids[] = bean.findMonitorDeadlockedThreads();
 
        if(ids != null)
        {
            ThreadInfo threadInfo[] = bean.getThreadInfo(ids);
 
            for (ThreadInfo threadInfo1 : threadInfo)
            {
                System.out.println(threadInfo1.getThreadId());    //Prints the ID of deadlocked thread
 
                System.out.println(threadInfo1.getThreadName());  //Prints the name of deadlocked thread
 
                System.out.println(threadInfo1.getLockName());    //Prints the string representation of an object for which thread has entered into deadlock.
 
                System.out.println(threadInfo1.getLockOwnerId());  //Prints the ID of thread which currently owns the object lock
 
                System.out.println(threadInfo1.getLockOwnerName());  //Prints name of the thread which currently owns the object lock.
            }
        }
        else
        {
            System.out.println("No Deadlocked Threads");
        }
    }
}


How To Avoid The Deadlock In Java

Deadlock is a dangerous condition, if it happens, it will bring the whole application to complete halt. So, extra care needs to be taken to avoid the deadlock. Followings are some tips that can be used to avoid the deadlock in java.

  • Try to avoid nested synchronized blocks. Nested synchronized blocks makes a thread to acquire another lock while it is already holding one lock. This may create the deadlock if another thread wants the same lock which is currently held by this thread.

synchronized (Lock A){

//Some statements

 

synchronized (Lock B)    {

//Try to avoid this block

}

}

  • Lock Ordering :

If you needed nested synchronized blocks at any cost, then make sure that threads acquire the needed locks in some predefined order. For example, if there are three threads t1, t2 and t3 running concurrently and they needed locks A, B and C in the following manner,

Thread t1:

Lock A

Lock B

Thread t2:

Lock A

Lock C

Thread t3:

Lock A

Lock B

Lock C

In the above scenario, t1 needs A and B locks, t2 needs A and C locks and t3 needs A, B and C locks. If you define an order to acquire the locks like, Lock A must be acquired before Lock B and Lock B must be acquired before Lock c, then deadlock never occurs in the above case.

If you define such lock ordering, then thread t2 never acquire lock C and t3 never acquire lock B and lock C until they got lock A. They will wait for lock A until it is released by t1. After lock A is released by t1, any one of these threads will acquire lock A on the priority basis and finishes their task. Other thread which is waiting for lock A, will never try to acquire remaining locks.

By defining such lock ordering, you can avoid the deadlock.

  • Lock Timeout :

Another deadlock preventive tip is to specify the time for a thread to acquire the lock. If it fails to acquire the specified lock in the given time, then it should give up trying for a lock and retry after some time. Such method of specifying time to acquire the lock is called lock timeout.

  • Lock the code where it is actually needed. For example, if you want only some part of the method to be thread safety, then lock only that part not the whole method.

void method(){

//Some statements

 

synchronized (this)    {

//Locking only some part of the method    }    //Some statements}


Interthread Communication Using wait(), notify() and notifyAll()

Threads can communicate with each other using wait(), notify() and notifyAll() methods. These methods are final methods of java.lang.Object class. That means every class in java will have these methods. Below is the method signatures of these methods.

1) public final void wait() throws InterruptedException

This method tells the currently executing thread to release the lock of this object and wait until some other thread acquires the same lock and notify it using either notify() or notifyAll() methods. This method throws InterruptedException if waiting thread is interrupted.

2)public final void notify()

This method wakes up one thread randomly that called wait() method on this object.

3) public final void notifyAll()

This method wakes up all the threads that called wait() method on this object. But, only one thread will acquire lock of this object depending upon the priority.

Important Note : These three methods must be called within synchronized method or block. Any thread which calls these methods must have lock of that object.

Below is an example for using wait() and notify() methods.

{
    synchronized void methodOne()
    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getName()+" is relasing the lock and going to wait");
 
        try
        {
            wait();        //releases the lock of this object and waits
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        System.out.println(t.getName()+" got the object lock back and can continue with it's execution");
    }
 
    synchronized void methodTwo()
    {
        Thread t = Thread.currentThread();
 
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        notify();     //wakes up one thread randomly which is waiting for lock of this object
 
        System.out.println("A thread which is waiting for lock of this object is notified by "+t.getName());
    }
}
 
public class ThreadsInJava
{
    public static void main(String[] args)
    {
        final Shared s = new Shared();
 
        Thread t1 = new Thread()
        {
            public void run()
            {
                s.methodOne();   //t1 calling methodOne() of 's' object
            }
        };
 
        Thread t2 = new Thread()
        {
            @Override
            public void run()
            {
                s.methodTwo();   //t2 calling methodTwo() of 's' object
            }
        };
 
        t1.start();
 
        t2.start();
    }
}

 

In this example, Thread t1 and t2 are sharing shared class object ‘s’. Thread t1 is calling methodOne() and thread t2 is calling methodTwo() of ‘s’ object. Both the methods are synchronized. That means, for any thread to enter these methods, they must acquire lock of ‘s’ object.

First, thread t1 acquires the object lock and enters methodOne(). Thread t2 waits for thread t1 to release the object lock. Thread t1 calls wait() method within methodOne(). As soon as, it calls wait() method, It releases the lock of ‘s’ object and goes for wait. Thread t2 acquires this lock and enters methodTwo(). After entering methodTwo(), thread t2 sleeps for 5 seconds and calls notify() method on this object. It wakes up thread t1 which is waiting for this object lock. As soon as, thread t2 releases the object lock after finishing it’s execution of methodTwo(), thread t1 acquires this lock and executes remaining statements of methodOne(). In this manner, both threads t1 and t2 communicate with each other and share the lock.

 


Some Things-To-Remember About wait(), notify() and notifyAll() :

  • If a thread calls notify() method and more than one threads are waiting for the object lock, then only one thread will be notified randomly.
  • When a thread calls notifyAll() method on an object, it notifies all the threads which are waiting for this object lock. But, only one thread will acquire this object lock depending upon priority.
  • When you call sleep() method on a thread, thread goes to sleep with holding the object lock with it. But, if you call wait() method, thread releases the object lock and goes for sleep. This is the main difference between wait() and sleep() methods.
  • wait(), notify() and notifyAll() are final methods oflang.Object class not java.lang.Thread class.
  • wait(), notify() and notifyAll() – all these three methods throw IllegalMonitorStateExceptionif the calling thread does not owns the object lock.
  • wait() method is overloaded in Object class. There are two more wait() methods available in Object class. They are,

public final void wait(long timeOut)  —>  This makes current thread to wait until any other thread calls notify() or notifyAll() on this object or specified time(milli seconds) has elapsed.

public final void wait(long timeOut, int nanos)  —>  This makes current thread to wait until any other thread calls notify() or notifyAll() on this object or specified time(milli seconds + nano seconds) has elapsed.


Thread Interruption In Java

Thread interruption in java is a mechanism in which a thread which is either sleeping or waiting can be made to stop sleeping or waiting. Thread interruption is like telling the thread that it should stop waiting or sleeping and return to running status. Thread interruption is programmatically implemented using interrupt() method of java.lang.Thread class. interrupt() method is a non-static public method of Thread class. Here is the method signature of interrupt() method.

public void interrupt()

The whole thread interruption mechanism depends on an internal flag called interrupt status. The initial value of this flag for any thread is false. When you call interrupt() method on a thread, interrupt status of that thread will be set to true. When a thread throws InterruptedException, this status will be set to false again. Remember, InterruptedException is thrown when a thread is interrupted while it is sleeping or waiting. Many methods of Thread class like sleep(), wait(), join() throw InterruptedException.

Here is an example for interrupting a sleeping thread using interrupt() method.
public class ThreadsInJava{
    public static void main(String[] args)    {
        Thread t = new Thread()        {
            public void run()            {
                try                {
                    Thread.sleep(10000);        //Thread is sleeping for 10 seconds
                }
                catch (InterruptedException e)                {
                    System.out.println("Thread is interrupted");
                }
            }
        };
         t.start();
         try        {
            Thread.sleep(3000);      //Main thread is sleeping for 3 seconds
        }        catch (InterruptedException e)        {
            e.printStackTrace();
        } 
        t.interrupt();         //main thread is interrupting thread t
    }
}
In the above example, main thread is creating and starting thread t. Thread t is going to sleep for 10 seconds as soon as it started. main thread, after starting thread t, is also going to sleep for 3 seconds. After sleeping for 3 seconds, main thread calls interrupt() method on thread t. It interrupts sleeping thread t. It causes the InterruptedException.

Some Things-To-Remember About Thread Interruption In Java :

You can check whether a particular thread is interrupted or not using isInterrupted() method of Thread class. This method returns current interrupt status of a thread.

public class ThreadsInJava{
    public static void main(String[] args)    {
        Thread t = new Thread()        {
            public void run()            {
                System.out.println(isInterrupted());         //Output : true
                 try  {
                    Thread.sleep(10000);        //Thread is going to sleep for 10 seconds
                }   catch (InterruptedException e)  {
                    System.out.println("Thread is interrupted");
                }
                 System.out.println(isInterrupted());       //Output : false
            }
        };
         t.start();
         t.interrupt();         //main thread is interrupting thread t
    }
}

 

7 Things Every Java Programmer Should Know About Threads In Java

Here, I have tried to make a list of some observations about threads in java. You may be asked about these points in the interviews. I hope you guys will find it useful.

1) If you start a thread that is already started, you will get java.lang.IllegalThreadStateException at run time. There will be no compilation errors.

public class ThreadsInJava{
    public static void main(String[] args)
    {
        Thread t = new Thread();
 
        t.start();
 
        t.start();    //This statement will throw java.lang.IllegalThreadStateException
    }
}

2) Exception is thread wise not execution wise. i.e exception effects the thread in which it occurs. Other threads will execute normally. In the below example, exception occurs in thread t1. only this thread will be terminated abruptly. Thread t2 will continue to execute it’s task.

{
    public static void main(String[] args)
    {
        Thread t1 = new Thread()
        {
            public void run()
            {
                String s = null;
 
                System.out.println(s.length());  //This statement will throw NullPointerException
 
                System.out.println("This statement will not be executed");
            }
        };
 
        Thread t2 = new Thread()
        {
            public void run()
            {
                for(int i = 0; i <= 1000; i++)
                {
                    System.out.println(i);
                }
            }
        };
 
        t1.start();
 
        t2.start();
    }
}

3) As we all know that start() method internally calls run() method. What happens when you call run() method directly?. When you call run() method of a thread directly, calling thread will execute the task defined in the run() method. For example, in the below program main thread is calling run() method of thread t. In this case, main thread will execute run() method not thread t.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread t = new Thread()
        {
            public void run()
            {
                System.out.println(Thread.currentThread().getName());    //Output : main
            }
        };
 
        t.run();
    }
}

4) Which one is better way to implement threads in java. Is it using Thread class or using Runnable interface?. It is the most confusing question for a java developer. I am of opinion that when multiple threads need to execute same task, then use Runnable interface. If multiple threads need to execute different tasks, then go for Thread class.

5) Setting the priority to a thread is not effective as we thought. Setting Priority of a thread is just an advice to OS not an instruction. It is up to OS to consider this advice.

6) Every thread in java is a member of a thread group. When a java application first starts up, Java runtime system creates a thread group called main. main thread is also member of this group.

public class ThreadsInJava
{
    public static void main(String[] args)
    {
        Thread t = Thread.currentThread();
 
        System.out.println(t.getThreadGroup());    
 
        //Output : java.lang.ThreadGroup[name=main,maxpri=10]
    }
}

7) A thread is a permanent member of a thread group to which it joins during creation. You can’t move a thread to a new group after creating it.


Difference Between wait() and sleep() Methods In Java

wait() and sleep() methods in java, are used to pause the execution of a particular thread in a multi threaded environment. Whenever a thread calls wait() method, it releases the lock or monitor it holds and whenever a thread calls sleep() method, it doesn’t release the lock or monitor it holds. This is the main difference between sleep() and wait() methods.

Below is the list of all differences between wait() and sleep() methods in java.

Differences Between wait() And sleep() Methods In Java :

  • Both wait() and sleep() methods are used to pause the execution of current thread for some period of time. Whenever a thread calls wait() method, it goes into WAITING state after releasing the lock it holds. Whenever a thread calls sleep() method, it goes into TIMED_WAITING state without releasing the lock it holds.
  • A thread which is in WAITING state (state after calling wait() method) can be woken up by other threads by callingnotify() or notifyAll() methods on the same lock. But, a thread which is in TIMED_WAITING state (state after calling sleep() method) can not be woken up. If any threads interrupt sleeping thread, InterruptedException will be raised.
  • wait() method along with notify() and notifyAll() are used for inter thread communication where as sleep() method is used to pause the execution of current thread for specific period of time.
  • wait() method is an instance method of java.lang.Object class. That means, this method is available in all objects you create in java. Where as sleep() method is a static method of java.lang.Thread class. That means, it is available only in threads.
  • wait() method is called on objects. Whenever it is called by a thread on a particular object, thread releases the lock of that object and waits until other threads call either notify() or notifyAll() methods on the same object. Where as sleep() method is called on threads.
  • Whenever sleep() method is called, only current thread is going for sleep. For example, if main thread calls sleep() method on a thread t, i.e t.sleep(), main thread itself is going to sleep not thread t.
  • To call wait() method, calling thread must hold the lock of the object on which it is calling wait() method. That means, wait() method must be called within the synchronized block. Where as to call sleep() method, thread need not to hold the object lock. That means, sleep() method can be called outside the synchronized block also.

Below is the quick recap of above points.

wait() sleep()
The thread which calls wait() method releases the lock it holds. The thread which calls sleep() method doesn’t release the lock it holds.
The thread regains the lock after other threads call either notify() or notifyAll() methods on the same lock. No question of regaining the lock as thread doesn’t release the lock.
wait() method must be called within the synchronized block. sleep() method can be called within or outside the synchronized block.
wait() method is a member of java.lang.Object class. sleep() method is a member of java.lang.Thread class.
wait() method is always called on objects. sleep() method is always called on threads.
wait() is a non-static method of Object class. sleep() is a static method of Thread class.
Waiting threads can be woken up by other threads by calling notify() or notifyAll() methods. Sleeping threads can not be woken up by other threads. If done so, thread will throw InterruptedException.
 To call wait() method, thread must have object lock.  To call sleep() method, thread need not to have object lock.

Difference Between User Threads Vs Daemon Threads In Java

There are two types of threads in java. One is User Thread and another one is Daemon Thread. User threads are high priority threads which always run in foreground. Where as Daemon threads are low priority threads which always run in background. User threads are designed to do some specific task where as daemon threads are used to perform some supporting tasks. In this post, we will discuss some of the differences between user thread vs daemon thread and see how they differ from each other.

1) User threads are created by the application (user) to perform some specific task. Where as daemon threads are mostly created by the JVM to perform some background tasks like garbage collection.

2) JVM will wait for user threads to finish their tasks. JVM will not exit until all user threads finish their tasks. On the other side, JVM will not wait for daemon threads to finish their tasks. It will exit as soon as all user threads finish their tasks.

3) User threads are high priority threads, They are designed mainly to execute some important task in an application. Where as daemon threads are less priority threads. They are designed to serve the user threads.

4) User threads are foreground threads. They always run in foreground and perform some specific task assigned to them. Where as daemon threads are background threads. They always run in background and act in a supporting role to user threads.

5) JVM will not force the user threads to terminate. It will wait for user threads to terminate themselves. On the other hand, JVM will force the daemon threads to terminate if all the user threads have finished their task.

6) User threads are chosen to do the core work of an application. The application is very much dependent on the user threads for it’s smooth execution. Where as daemon threads are chosen to do some supporting tasks. The application is less dependent on the daemon threads for it’s smooth running.

User Threads Vs Daemon Threads In Java :

Below is the quick recap of the above points.

User Threads Daemon Threads
JVM waits for user threads to finish their work. It will not exit until all user threads finish their work. JVM will not wait for daemon threads to finish their work. It will exit as soon as all user threads finish their work.
User threads are foreground threads. Daemon threads are background threads.
User threads are high priority threads. Daemon threads are low priority threads.
User threads are created by the application. Daemon threads, in most of time, are created by the JVM.
User threads are mainly designed to do some specific task. Daemon threads are designed to support the user threads.
JVM will not force the user threads to terminate. It will wait for user threads to terminate themselves. JVM will force the daemon threads to terminate if all user threads have finished their work.

Extends Thread Vs Implements Runnable In Java

There are two ways you can create the threads in java. One is by extending java.lang.Thread class and another one is by implementing java.lang.Runnable interface [more]. In this post, we will see the differences between “Extends Thread” and “Implements Runnable” and what is the best option between these two to create the threads in java.

Differences Between Extends Thread And Implements Runnable In Java :

1) Multiple Inheritance Limitation

As you know, Java doesn’t support multiple inheritance. A class in java can extend only one class. If you extend Thread class, then your class will not be able to extend any other class. This will limit your class to thread behavior. If you implement Runnable interface, then you will have an option for your class to extend any other class and inherit behaviors from other class also.

2) Overhead Of Additional Methods

If you extend Thread class, all methods of Thread class will be inheriting to your class which you may not need. This will cause additional overhead. You can remove this overhead by implementing Runnable interface.

3) Logical Separation Of Task From The Runner

If you implement Runnable interface, it will separate actual task from the runner. Runnable interface represents only the task and you can pass this task to any type of runner, either a thread or any executors.

4) Best Object Oriented Design Practice

In object oriented programming, extending a class means modifying or improving the existing class. If you are not improving the class, then it is not a good practice to extend it. So, implementing Runnable will be the best object oriented design practice.

 

5) Loosely Coupled Vs Tightly coupled

“Implements Runnable” makes your code loosely coupled. Because it separates the task from the runner. “Extends Thread” will make your code tightly coupled. Because, single class will act as both task container as well as runner.

6) Reusability

Implementing Runnable improves the reusability of your code. Because, Runnable contains only the task and you can use it wherever and whenever you want.

7) Specialization Vs Generalization

“Extends Thread” gives more specialized code. Because, it defines the thread specific task. Where as “Implements Runnable” gives more generalized version of the task applicable to many threads.

8) Maintenance

“Implements Runnable” will make your code easily maintainable as it separates the task from the runner. If you want to modify the task at any time, you can do so easily without disturbing the runner.

9) Example

a) Extends Thread Class
class MyThread extends Thread
{
    @Override
    public void run()
    {
        //Keep the task to be performed here
    }
}
 
public class MainClass 
{   
    public static void main(String[] args) 
    {
        MyThread thread = new MyThread();
         
        thread.start();
    }    
}
b) Implements Runnable Interface
class MyRunnable implements Runnable
{
    @Override
    public void run()
    {
        //Keep the task to be performed here
    }
}
 
public class MainClass 
{   
    public static void main(String[] args) 
    {
        MyRunnable runnable = new MyRunnable();
         
        Thread t = new Thread(runnable);
         
        t.start();
    }    
}

Extends Thread Vs Implements Runnable In Java :

Implements Runnable Extends Thread
You can extend any other class. You can’t extend any other class.
No overhead of additional methods . Overhead of additional methods from Thread class.
Separates the task from the runner. Doesn’t separate the task from the runner.
Best object oriented programming practice. Not a good object oriented programming practice.
Loosely coupled. Tightly coupled.
Improves the reusability of the code. Doesn’t improve the reusability of the code.
More generalized task. Thread specific task.
Maintenance  of the code will be easy. Maintenance of the code will be time consuming.