Java ScheduledThreadPoolExecutor - Scheduling With ExecutorService

ScheduledThreadPoolExecutor in Java adds functionality to schedule commands to run after a given delay, or to execute periodically. Since ScheduledThreadPoolExecutor is an ExecutorService so it uses thread from a thread pool to execute tasks.

Java ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor class is part of Java Executor framework with in the Java concurrent API. This class extends ThreadPoolExecutor and implements ScheduledExecutorService interface.

Java ScheduledThreadPoolExecutor constructors

  • ScheduledThreadPoolExecutor(int corePoolSize)- Creates a new ScheduledThreadPoolExecutor with the given core pool size.
  • ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler)- Creates a new ScheduledThreadPoolExecutor with the given initial parameters.
  • ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)- Creates a new ScheduledThreadPoolExecutor with the given initial parameters.
  • ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)- Creates a new ScheduledThreadPoolExecutor with the given initial parameters.

The parameters used in these constructors of the ScheduledThreadPoolExecutor class are as follows-

  • corePoolSize- The number of threads to keep in the pool. These number of threads will always be created even if they are idle, unless allowCoreThreadTimeOut is set.
  • threadFactory- the factory to use when the executor creates a new thread.
  • handler- the handler to use when execution is blocked because the thread bounds and queue capacities are reached.

Creating ScheduledThreadPoolExecutor instance using Executors factory methods

It is recommended to use static factory methods provided by the Executors class to get a ScheduledThreadPoolExecutor rather than creating instances of ThreadPoolExecutor directly using one of the above constructors.

  • newSingleThreadScheduledExecutor()- Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically.
  • newSingleThreadScheduledExecutor(ThreadFactory threadFactory)- Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically.
  • newScheduledThreadPool(int corePoolSize)- Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
  • newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)- Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.

Scheduling methods in Java ScheduledThreadPoolExecutor

  • schedule(Runnable command, long delay, TimeUnit unit)- Schedules a Runnable task to execute after the given delay.
  • schedule(Callable<V> callable, long delay, TimeUnit unit)- Submits a Callable task to execute after the given delay.
  • scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)- Submits a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period. For example if the initial delay is 5 seconds and the period is 2 seconds then the first task will be executed after the delay of 5 seconds and then periodic execution will happen after every 2 seconds- initialDelay + period, initialDelay + 2 * period and so on.
  • scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)- Submits a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next. For example if the initial delay is 5 seconds and the period is 2 seconds then the first task will be executed after the delay of 5 seconds and the second task will be scheduled to run after- (termination of first task + 2 seconds).

All these scheduling methods return a result of type ScheduledFuture which adds delay capabilities by extending Delayed interface apart from Future interface.

Java ScheduledThreadPoolExecutor example – Scheduling Runnable

In this example Executors.newSingleThreadScheduledExecutor() method is used to get a single-threaded executor for scheduling. In the schedule method delay is set as 5 seconds so the task should be executed after that delay.

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.schedule(new Task(), 5, TimeUnit.SECONDS);
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        "Executed at- " + new Date());
  }
}
Output
Time before execution started- Sat Jan 05 19:11:33 IST 2019
Executing task (thread name)- pool-1-thread-1Executed at- Sat Jan 05 19:11:38 IST 2019

Java ScheduledThreadPoolExecutor’s scheduleAtFixedRate() method example

This example shows how you can do periodic scheduling using scheduleAtFixedRate() method. Executors.newScheduledThreadPool(2) method is used to create a thread pool of two threads. Note the use of awaitTermination() method which ensures tasks are scheduled otherwise shutdown() method won’t let the scheduling of new tasks to happen.

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.scheduleAtFixedRate(new Task(), 5, 2, TimeUnit.SECONDS);
    try {
      // To terminate task execution after 10 seconds
      scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        " Executed at- " + new Date());
    // adding delay to keep the thread busy
    // so that another thread from pool is used
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Time before execution started- Sat Jan 05 19:22:13 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:22:19 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:22:21 IST 2019
Executing task (thread name)- pool-1-thread-2 Executed at- Sat Jan 05 19:22:23 IST 2019

As you can see first task is scheduled to run after the initial delay of 5 seconds later tasks are scheduled to run after delay of 2 seconds.

Java ScheduledThreadPoolExecutor’s scheduleWithFixedDelay() method example

This example shows how you can do periodic scheduling using scheduleWithFixedDelay() method.

public class ScheduledThread {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
    System.out.println("Time before execution started- " + new Date());
    scheduledExecutor.scheduleWithFixedDelay(new Task(), 5, 2, TimeUnit.SECONDS);
    try {
      // To terminate task execution after 10 seconds
      scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

class Task implements Runnable{
  @Override
  public void run() {
    System.out.println("Executing task (thread name)- " + Thread.currentThread().getName() +
        " Executed at- " + new Date());
    // adding delay to keep the thread busy
    // so that another thread from pool is used
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Time before execution started- Sat Jan 05 19:34:13 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:34:18 IST 2019
Executing task (thread name)- pool-1-thread-1 Executed at- Sat Jan 05 19:34:22 IST 2019

As you can see first task is scheduled to run after the initial delay of 5 seconds later tasks are scheduled to run after the termination of previous task + 2 seconds.

Java ScheduledThreadPoolExecutor example using constructor

All the examples showed till now use Executors class factory methods which is the recommended way to get a ScheduledThreadPoolExecutor but you can also use constructor of the ScheduledThreadPoolExecutor class.

In the next example ScheduledThreadPoolExecutor instance is created using one of the constructor and then a callable is scheduled to execute after a delay of 3 seconds.

public class ScheduledThread {
  public static void main(String[] args) {
    // creating executor with core pool of 2 threads,  default Thread Factory
    // and handler uses abort policy
    ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(2, 
        Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    // Callable implementation
    Callable<String> c = ()->{
      System.out.println("Executed at- " + new Date());
      return "Executing task";
    };
    System.out.println("Time before execution started- " + new Date());
    // scheduling tasks with callable as param to be
    // executed after a delay of 3 Secs
    ScheduledFuture<String> sf = scheduledExecutor.schedule(c, 3, TimeUnit.SECONDS); 
    try {
      System.out.println("Value- " + sf.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}
Output
Time before execution started- Sat Jan 05 19:47:21 IST 2019
Executed at- Sat Jan 05 19:47:24 IST 2019
Value- Executing task

That's all for the topic Java ScheduledThreadPoolExecutor - Scheduling With ExecutorService. If something is missing or you have something to share about the topic please write a comment.


You may also like

Multiple Catch Blocks in Java

If hearing the term try-catch block is giving you an idea that you can have a try block and a single associated catch block then that is a wrong idea. You can have multiple catch blocks associated with a try block. In this post we’ll see examples of multiple catch blocks in Java exception handling.

Refer Multi-Catch Exception in Java to seen another way of grouping multiple catch blocks using multi-catch statement available from Java 7.

You enclose the code that may throw an exception in try block but the enclosed code may throw more than one exception too. In order to handle these exceptions you can provide multiple catch blocks in Java. If an exception is thrown the exception handling mechanism looks for the catch block with an argument that matches the type of the exception thrown. Only the matching catch clause out of the multiple catch blocks is executed. After the matching catch block is executed, execution continues after the try-catch block.

Example of multiple catch blocks in Java

In this example program there is an array of length 3 in the method calculateValue(). Index of the array is passed as an argument to the method. Since the array has value 0 at index 1 so passing 1 as an index will result in ArithmeticException because of the division by zero.

Same way passing 4 as an index will result in ArrayIndexOutOfBoundsException as the length of array is 3. To handle these multiple exception scenarios there are multiple catch blocks associated with the try block.

public class MultipleCatch {
  private void calculateValue(int i){
    int arr[] = {6, 0, 3};
    try{
      int num = 7/arr[i];
    }catch(ArithmeticException exp){
      exp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException exp){
      exp.printStackTrace();
    }catch(Exception exp){
      exp.printStackTrace();
    }
    System.out.println("After the try-catch block");
  }

  public static void main(String[] args) {
    MultipleCatch obj = new MultipleCatch();
    obj.calculateValue(1);
    obj.calculateValue(4);
  }
}
Output
java.lang.ArithmeticException: / by zero
	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:7)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:21)
After the try-catch block
java.lang.ArrayIndexOutOfBoundsException: 4
	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:7)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:22)
After the try-catch block

Maintaining exception hierarchy in multiple catch blocks

While using multiple catch blocks in Java you will have to keep exception hierarchy in mind, which means you will have to ensure that any exception super class doesn’t come before its exception sub-classes.

This should be ensured because a catch statement having an exception super class as an argument will be able to catch exception of its type and any of its subclass too. Thus, placing a catch statement having sub-class as an argument after the catch statement with super class as argument would mean the catch statement with sub-class is unreachable. Moreover unreachable code causes compile time error in Java so you will get compilation error for any such misplaced catch statement.

In the previous example the last catch statement has Exception class object as an argument to catch any other type of exception. Since Exception class is super class of both the ArithmeticException and ArrayIndexOutOfBoundsException so placing that catch statement first will result in compile time error. Just tweak the above example and place the catch statement with Exception class object as argument before the other catch blocks.

public class MultipleCatch {
  private void calculateValue(int i){
    int arr[] = {6, 0, 3};
    try{
      int num = 7/arr[i];
    }
    catch(Exception exp){
      exp.printStackTrace();
    }catch(ArithmeticException exp){
      exp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException exp){
      exp.printStackTrace();
    }
    System.out.println("After the try-catch block");
  }

  public static void main(String[] args) {
    MultipleCatch obj = new MultipleCatch();
    obj.calculateValue(1);
    obj.calculateValue(4);
  }
}

That will result in compile time error with compiler complaining about the unreachable code.

Unresolved compilation problems: 
	Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception
	Unreachable catch block for ArrayIndexOutOfBoundsException. It is already handled by the catch block for Exception

	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:11)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:21)

Important points

  1. There may be multiple catch blocks after a try block.
  2. If an exception is thrown in try block the catch block with matching exception type is executed.
  3. Only one of the multiple catch blocks is executed.
  4. Multiple catch blocks must be placed in the order specific to general.

That's all for the topic Multiple Catch Blocks in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

How to Read Delimited File in Java

If you have to read delimited file in Java and parse it then you can do it using the following two ways-

  1. Using Scanner class with useDelimiter() method.
  2. Read file using BufferedReader line by line and then split each line using split()method.

Using Scanner class to read delimited file in Java

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches white space. The scanner can also use delimiters other than white space for that useDelimiter() method is used. Let’s see some examples of using Scanner class to read delimited file in Java.

Reading CSV file using Scanner in Java

Here is an example CSV file which denotes Account From, Account To and Amount Transferred.

1001,1003,2000
1006,2004,3000
1005,1007,10000

Which you want to read using Scanner class and parse it to display the fields.

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class ReadDelimited {
  public static void main(String[] args) {
    Scanner sc = null;
    try {
      sc = new Scanner(new File("D:\\acct.csv"));

      // Check if there is another line of input
      while(sc.hasNextLine()){
        String str = sc.nextLine();
        // parse each line using delimiter
        parseData(str);
      }
    } catch (IOException  exp) {
      // TODO Auto-generated catch block
      exp.printStackTrace();
    }finally{
      if(sc != null)
        sc.close();
    }	  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    Scanner lineScanner = new Scanner(str);
    lineScanner.useDelimiter(",");
    while(lineScanner.hasNext()){
      acctFrom = lineScanner.next();
      acctTo = lineScanner.next();
      amount = lineScanner.next();
      System.out.println("Account From- " + acctFrom + " Account To- " + acctTo + 
       " Amount- " + amount);  
    }
    lineScanner.close();
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

Reading pipe (|) delimited file in Java using Scanner

Here is another example Java program showing how you can read pipe delimited data using Scanner in Java.

1001|1003|2000
1006|2004|3000
1005|1007|10000

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class ReadDelimited {
  public static void main(String[] args) {
    Scanner sc = null;
    try {
      sc = new Scanner( new File("D:\\test.txt"));
      
      // Check if there is another line of input
      while(sc.hasNextLine()){
        String str = sc.nextLine();
        // parse each line using delimiter
        parseData(str);
      }
     
    } catch (IOException  exp) {
      // TODO Auto-generated catch block
      exp.printStackTrace();
    }finally{
      if(sc != null)
        sc.close();
    }	  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    Scanner lineScanner = new Scanner(str);
    lineScanner.useDelimiter("\\|");
    while(lineScanner.hasNext()){
      acctFrom = lineScanner.next();
      acctTo = lineScanner.next();
      amount = lineScanner.next();
      System.out.println("Account From- " + acctFrom + " Account To- " + acctTo + 
         " Amount- " + amount);  
    }
    lineScanner.close();
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

Since pipe symbol is a reserved character you do need to escape it, that is why lineScanner.useDelimiter("\\|"); is used.

Using split() method to split delimited data

Another way to read delimited file in Java is to read file line by line, you can use BufferedReader to read the file and then split delimited data using split method. If we take the same pipe delimited file as used above then the Java example is as follows.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadDelimited {
  public static void main(String[] args) {
    BufferedReader br = null;
    try{
      String strLine;
      //FileReader instance wrapped in a BufferedReader
      br = new BufferedReader(new FileReader("D:\\test.txt"));
       
      while((strLine = br.readLine()) != null){
        parseData(strLine);
      }
    }catch(IOException exp){
      System.out.println("Error while reading file " + exp.getMessage());
    }finally {
      try {
        // Close the stream
        if(br != null){
          br.close();
        }
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    // parsing using split method
    String[] data = str.split("\\|");
    System.out.println("Account From- " + data[0] + " Account To- " + data[1] + 
         " Amount- " + data[2]);  
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

That's all for the topic How to Read Delimited File in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

How to Read Input From Console in Java

If you have to read input from console in Java there are 3 options.

  1. Using BufferedReader class. See example.
  2. Using Scanner class, available from Java 5. See example.
  3. Using System.console() method, available from Java 6. See example.

Using BufferedReader class

By wrapping the standard input stream "System.in" in an InputStreamReader which is further wrapped with in a BufferedReader you can read input from console in Java.

public class ConsoleReader {
  public static void main(String[] args) {
    // Wrapping InputStreamReader and System.in
    BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Enter City Name: ");            
    try {            
      String cityName = bufferRead.readLine();
      System.out.println("Entered city name- " + cityName);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Enter City Name: Delhi
Entered city name- Delhi

Using Scanner class

Another option to read input from console in Java is to use Scanner class. A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values. For scanning input there are convenient methods for different data types like nextInt(), nextDouble(), nextFloat() etc.

public class ConsoleReader {
  public static void main(String[] args) {
    System.out.print("Enter Values: ");                             
    Scanner sc = new Scanner(System.in);
    System.out.println("Entered Line- " + sc.nextLine());
    System.out.println("Entered integer value- " + sc.nextInt());
    System.out.println("Entered double value- " + sc.nextInt());
    sc.close();
  }
}
Output
Enter Values: Delhi
Entered Line- Delhi
56 67.89
Entered integer value- 56
Entered double value- 67.89

Using System.console method

You can also use System.console to read input from console in Java. One of the advantage of using System.console() method is that it returns a Console object which has a method readPassword() which can be used for reading a password or passphrase from the console with echoing disabled.

public class ConsoleReader {
  public static void main(String[] args) {
    //Using System.console()
    String username = System.console().readLine("Enter City Name: ");   
    System.out.println("Entered city name- " + username); 
  }
}
Output
Enter City Name: Delhi
Entered city name- Delhi
Using System.console method to read password
public class ConsoleReader {
  public static void main(String[] args) {
    //Using System.console()
    System.out.print("Enter password: ");
    char[] username = System.console().readPassword();   
    System.out.println("Entered password- " + username.toString()); 
  }
}
Output
Enter password:
Entered password- [C@75bd9247

As you can see echoing for the password is disabled.

That's all for the topic How to Read Input From Console in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

Java Volatile Keyword With Examples

In this post we’ll see what is volatile keyword in Java, when to use volatile variable and what is the reason for declaring variable as volatile.

What is volatile keyword in Java

To know volatile keyword in Java better you would have to know a little about the optimizations that happens for the variables with in the Java memory model. Let’s say you have a variable test declared in your code. You would think that test variable will be stored only in RAM and all the threads will read the value of the test variable from there. But the processors, in order to make processing faster, would hold the value of the variable in its cache. In that case any change to the value is written back to the main memory only when the synchronization between the cache and the memory happens.

That will cause problem where multiple threads are reading or writing a shared variable. If we take our example of test variable which is used among multiple threads, there may be a scenario that one thread has made changes to test variable which is still stored in cache and another thread tries to read the value of test variable from the main memory. That will result in memory inconsistency errors as different threads will read/write different values of test variable.

volatile keyword in java

How declaring variable as volatile in Java helps

Declaring a variable as volatile ensures that value of the variable is always read from the main memory. So declaring a field as volatile in Java gives visibility guarantee that a write to a volatile field happens-before every subsequent read of that field.

Problem we saw above because of value being cached by the CPU will not happen with volatile field as it is guaranteed that updates done by thread-1 to the volatile variable will always be visible to thread-2.

Volatile Java example code

One of the most common use of the volatile keyword in Java is boolean status flags declared as volatile, where the flag indicates completion of event so that another thread can start.

Let’s first see what will happen if volatile is not used in such case.

public class VolatileDemo {
  private static  boolean flag = false;
  public static void main(String[] args) {
    // Thread-1
    new Thread(new Runnable(){
      @Override
      public void run() {
        for (int i = 1; i <= 2000; i++){
          System.out.println("value - " + i);
        }
        // changing status flag
        flag = true;
        System.out.println("status flag changed " + flag );
      }			
    }).start();
    // Thread-2
    new Thread(new Runnable(){		
      @Override
      public void run() {
        int i = 1;
        while (!flag){
          i++;
        }
        System.out.println("Start other processing " + i);    
      }
    }).start();
  }
}
Output
....
....
value - 1997
value - 1998
value - 1999
value - 2000
status flag changed true

On running this code you will see that the first thread displays value of i till 2000 and change the status flag but the second thread won’t print the message "Start other processing " and the program won’t terminate. Since flag variable is accessed frequently in the thread-2 in the while loop, the compiler may optimize by placing the value of flag in a register, then it will keep testing the loop condition (while (!flag)) without reading the value of flag from main memory.

Now if you change the boolean variable flag and mark it as volatile that will guarantee that the change done to the shared variable by one thread is visible to other threads.

private static volatile boolean flag = false;
Output
....
....
value - 1997
value - 1998
value - 1999
value - 2000
status flag changed true
Start other processing 68925258

Volatile also ensures reordering of statements doesn’t happen

When a thread reads a volatile variable, it not only sees the latest change to the volatile, but also the side effects of the code that led up the change. That is also known as the happens before extended guarantee which is provided by volatile keyword from Java 5.

For example, If thread T1 changes other variables before updating the volatile variable then thread T2 will get the updated variable of those variables too that were changed before the update of volatile variable in thread T1.

That brings us to the point of reordering that may happen at compile-time for optimizing the code. The code statements may be reordered as long as the semantic meaning is not changed.

private int var1;
private int var2;
private volatile int var3;
public void calcValues(int var1, int var2, int var3){
  this.var1 = 1;
  this.var2 = 2;
  this.var3 = 3;
}

Since var3 is volatile so, because of happens-before extended guarantee, updated values of var1 and var2 will also be written to main memory and visible to other threads.

What if these statements are re-ordered for optimization.

this.var3 = 3;
this.var1 = 1;
this.var2 = 2;

Now the values of variables var1 and var2 are updated after update of volatile variable var3. So the updated values of these variables var1 and var2 may not be available to other threads.

That is why reordering is not permitted if read or write of volatile variable happens after the update to other variables.

Volatile ensures visibility not atomicity

In the scenario where only one thread is writing to a variable and other thread is just reading (like in case of status flag) volatile helps in the correct visibility of the value of the variable. But volatile is not enough if many threads are reading and writing the value of the shared variable. In that case because of race condition threads may still get wrong values.

Let's clear it with a  Java example in which there is a class SharedData whose object is shared among the thread. With in the SharedData class counter variable is marked as volatile. Four threads are created that increment the counter and then display the updated value. Because of the race condition threads may still get wrong values. Note that you may get the correct values also in few runs.

public class VolatileDemo implements Runnable {
  SharedData obj = new SharedData();
  public static void main(String[] args) {
    VolatileDemo vd = new VolatileDemo();
    new Thread(vd).start();
    new Thread(vd).start();
    new Thread(vd).start();
    new Thread(vd).start();
  }

  @Override
  public void run() {
    obj.incrementCounter();
    System.out.println("Counter for Thread " + Thread.currentThread().getName() + 
        " " + obj.getCounter());
  }	
}

class SharedData{
  public volatile int counter = 0;
  public int getCounter() {
    return counter;
  }

  public void incrementCounter() {
    ++counter;
  }
}
Output
Counter for Thread Thread-0 1
Counter for Thread Thread-3 4
Counter for Thread Thread-2 3
Counter for Thread Thread-1 3

Important points about volatile in Java

  • Volatile keyword in Java can only be used with variables not with methods and classes.
  • A variable marked as volatile ensures that the value is not cached and the updates to the volatile variables are always done in main memory.
  • Volatile also ensures that the reordering of the statements don’t happen that way volatile provides happens-before extended guarantee where changes to other variables before the update of volatile variables are also written to main memory and visible to other threads.
  • Volatile ensures just visibility not the atomicity.
  • It is a compile-time error if a final variable is also declared volatile.
  • Using volatile is less expensive than using lock.
Related Posts

That's all for the topic Java Volatile Keyword With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

ThreadLocal Class in Java With Examples

In a multi-threaded environment a shared object would need synchronization to avoid corruption through concurrent access, but synchronization is expensive. Another alternative is to give each thread its own instance and avoid sharing of data. That’s what ThreadLocal class in Java does.

ThreadLocal class in Java provides thread local variables where each thread has its own, independently initialized copy of the variable.

How to create and access thread-local variables

Using ThreadLocal() constructor you can create a thread local variable. For example if you want to create a thread local variable that stores an integer value for individual threads.

private static final ThreadLocal<Integer> tcValue = new ThreadLocal<Integer>();

Here note that ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.

To get or set value to this thread local variable you can use get() and set() methods of the ThreadLocal class.

tcValue.set(1);
Integer threadId = tcValue.get();

You can use initialValue() method to return the current thread's "initial value" for this thread-local variable. This method will be invoked the first time a thread accesses the variable with the get() method. The default implementation of initialValue() in the ThreadLocal class just returns null.

If you want your thread-local variables to have an initial value other than null you need to subclass ThreadLocal and override initialValue() method.

Java 8 onward withInitial(Supplier<? extends S> supplier) method can also be used to create a thread local variable. Since this method uses Supplier functional interface as parameter so lambda expression can be used to implement it.

Here is a code snippet that puts these methods to use to make it clearer.

private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable with initialValue() implementation to 
//return initial value to each thread
private static final ThreadLocal threadId =
  new ThreadLocal() {
    @Override 
    protected Integer initialValue() {
      return nextId.getAndIncrement();
    }
  };

If you are using withInitial() method then you can replace initialValue() implementation with the following code.

private static final ThreadLocal<Integer> threadId  = 
     ThreadLocal.withInitial(()-> {return nextId.getAndIncrement();});

Java ThreadLocal class example

1- One use of ThreadLocal class is in the scenario where you want to associate state with each thread (user ID or Transaction ID). In that case you can assign thread-local variable to each thread with a unique value. Just to verify assigned IDs are displayed again in another method.

import java.util.concurrent.atomic.AtomicInteger;

class UniqueIdGenerator{
  private static final AtomicInteger nextId = new AtomicInteger(0);
  // ThreadLocal variable
  private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
    @Override 
    protected Integer initialValue() {
     return nextId.getAndIncrement();
    }
  };
  // Returns the current thread's unique ID, assigning it if necessary
  public static int getId() {
    return threadId.get();
  }
}
public class ThreadClassDemo implements Runnable{
  @Override
  public void run() {
    System.out.println("Thread " + Thread.currentThread().getName() 
        + " Value - " +  UniqueIdGenerator.getId());
    ThreadClassDemo td = new ThreadClassDemo();
    // display stored Id again to verify
    td.displayThreadId();
  }
	
  public void displayThreadId(){
    System.out.println("Thread " + Thread.currentThread().getName() 
          + " Stored Value - " +  UniqueIdGenerator.getId());
  }
  public static void main(String[] args) {
    //ThreadClassDemo td = new ThreadClassDemo();
    Thread thread1 = new Thread(new ThreadClassDemo());
    Thread thread2 = new Thread(new ThreadClassDemo());
    Thread thread3 = new Thread(new ThreadClassDemo());
    Thread thread4 = new Thread(new ThreadClassDemo());
    Thread thread5 = new Thread(new ThreadClassDemo());
    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();
    thread5.start();
  }
}
Output
Thread Thread-3 Value - 2
Thread Thread-0 Value - 0
Thread Thread-2 Value - 4
Thread Thread-4 Value - 3
Thread Thread-1 Value - 1
Thread Thread-1 Stored Value - 1
Thread Thread-4 Stored Value - 3
Thread Thread-2 Stored Value - 4
Thread Thread-0 Stored Value - 0
Thread Thread-3 Stored Value – 2

2- You can also use ThreadLocal as an alternative to synchronizing the code as synchronization is costly. When you use SimpleDateFormat in a multi-threaded environment you do need to synchronize it as instance of SimpleDateFormat is not thread safe. Using ThreadLocal you can construct instance of SimpleDateFormat per thread. Since each thread will have its own instance local to that thread so no chance of interference by another thread.

import java.text.SimpleDateFormat;
import java.util.Date;

class DateFormatInstance{
  // ThreadLocal variable
  private static final ThreadLocal<SimpleDateFormat> threadLocalDateFmt = 
      ThreadLocal.withInitial(()-> {return new SimpleDateFormat("dd/MM/yyyy");});

  public static SimpleDateFormat getFormat() {
    return threadLocalDateFmt.get();
  }
}
public class ThreadClassDemo implements Runnable{
  @Override
  public void run() {
    System.out.println(Thread.currentThread().getName() + " Date formatter pattern is - " 
      + DateFormatInstance.getFormat().toPattern());
    System.out.println("Formatted date - " 
      + DateFormatInstance.getFormat().format(new Date()));
  }
	
  public static void main(String[] args) {
    //ThreadClassDemo td = new ThreadClassDemo();
    Thread thread1 = new Thread(new ThreadClassDemo());
    Thread thread2 = new Thread(new ThreadClassDemo());
    Thread thread3 = new Thread(new ThreadClassDemo());

    thread1.start();
    thread2.start();
    thread3.start();
  }
}
Output
Thread-1 Date formatter pattern is - dd/MM/yyyy
Thread-2 Date formatter pattern is - dd/MM/yyyy
Thread-0 Date formatter pattern is - dd/MM/yyyy
Formatted date - 10/05/2018
Formatted date - 10/05/2018
Formatted date - 10/05/2018

Important points about ThreadLocal in Java

  1. Thread-local variable is local to a thread. Each thread has its own, independently initialized copy of the variable.
  2. Each thread has global access to its own thread-local variable. If a thread is calling several methods, thread-local variable can be accessed in all of those methods.
  3. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
  4. Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

Reference:https://docs.oracle.com/javase/10/docs/api/java/lang/ThreadLocal.html

Related Posts

That's all for the topic ThreadLocal Class in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

Sleep Method in Java Multi-Threading

Thread.sleep() method in Java multi-threading causes the currently executing thread to suspend execution for a specified period.

In Java Thread class there are two overloaded sleep() methods-

  1. static void sleep(long millis) throws InterruptedException- Causes the currently executing thread to sleep for the specified number of milliseconds.
  2. static void sleep(long millis, int nanos) throws InterruptedException- Causes the currently executing thread to sleep for the specified number of milliseconds plus the specified number of nanoseconds.

Important points about sleep() method in Java

  1. If the value of milliseconds is negative then IllegalArgumentException is thrown.
  2. If the value of nanoseconds is not in the range 0-999999 then IllegalArgumentException is thrown.
  3. Though you provide the duration thread is supposed to sleep as an argument in sleep method but that depends on the precision and accuracy of system timers and how schedulers are implemented in underlying OS.
  4. If thread is holding any lock, ownership of that lock is not released when thread is paused using sleep() method.
  5. A sleeping thread can also be interrupted thus terminating the sleep period.

Advantage of using sleep() method

sleep() method in Java helps in making processor time available to the other threads of an application or other applications that might be running on a computer system.

While developing your multi-threading application, using sleep() method, you can simulate some delay that may occur in production environment when your application is accessed by many users and executing many threads. That will help you to find out some of the errors that may crop up later.

Example using sleep() method

public class InterruptDemo implements Runnable {
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        System.out.println("Thread " + Thread.currentThread().getName() + " interrupted, reason " + e.getMessage());        
        throw new RuntimeException("Thread interrupted", e);
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    long startTime = System.currentTimeMillis();
    t.start();
    try {
      t.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
      System.out.println("Total thread pause time - " + (System.currentTimeMillis() - startTime));
  }
}
Output
Total thread pause time – 2527

As you can see loop in the run() method runs for 5 times so total sleep time would be 2500 ms but it is not that duration precisely.

Related Posts

That's all for the topic Sleep Method in Java Multi-Threading. If something is missing or you have something to share about the topic please write a comment.


You may also like

isAlive() And join() Methods in Java

In your application you may have a scenario where you spawn a bunch of threads to execute some logic and you want to start any further processing only after all the threads have finished the execution. Which means you need some way to know whether a thread is terminated or not. For that purpose Thread class provides isAlive() and join() methods in Java to check if a thread has finished executing or not.

isAlive() method in Java

This method tests if this thread is alive. A thread is alive if it has been started and has not yet died. Method returns true if thread is alive otherwise it returns false.

isAlive() method syntax
public final boolean isAlive()

join() method in Java

This method waits until the thread on which it is called terminates. There are three overloaded versions of join() method in Java Thread class.

  • public final void join() throws InterruptedException- Waits indefinitely for this thread to die.
  • public final void join(long millis) throws InterruptedException- Waits at most the time in milliseconds for this thread to die.
  • public final void join(long millis, int nanos) throws InterruptedException- Waits at most the time in milliseconds plus additional time in nanoseconds for this thread to die.

isAlive() and join() method Java example

Here is an example where five threads are created and you want to ensure that any further processing is done only after all these five threads finish executing the run() method and all these five threads are terminated.

First we’ll see what happens if join() method is not used.

class MyRunnable implements Runnable{
  @Override
  public void run() {
    System.out.println("In run method --" + Thread.currentThread().getName());	
    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }	
}

public class ThreadDemo {

  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnable());
    Thread t2 = new Thread(new MyRunnable());
    Thread t3 = new Thread(new MyRunnable());
    Thread t4 = new Thread(new MyRunnable());
    Thread t5 = new Thread(new MyRunnable());

    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();

    System.out.println("Is t1 Alive " + t1.isAlive());
    System.out.println("Is t2 Alive " + t2.isAlive());
    System.out.println("Is t3 Alive " + t3.isAlive());
    System.out.println("Is t4 Alive " + t4.isAlive());
    System.out.println("Is t5 Alive " + t5.isAlive());

    System.out.println("Now start further processing");
  }
}
Output
Is t1 Alive true
Is t2 Alive true
Is t3 Alive true
Is t4 Alive true
Is t5 Alive true
Now start further processing
In run method --Thread-1
In run method --Thread-0
In run method --Thread-2
In run method --Thread-3
In run method –Thread-4

As you can see from the output “Now start further processing” message is printed even before the threads started executing. But that is not what you want so let’s see how join() method can help in this scenario.

class MyRunnable implements Runnable{
  @Override
  public void run() {
    System.out.println("In run method --" + Thread.currentThread().getName());	
    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }	
}

public class ThreadDemo {

  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnable());
    Thread t2 = new Thread(new MyRunnable());
    Thread t3 = new Thread(new MyRunnable());
    Thread t4 = new Thread(new MyRunnable());
    Thread t5 = new Thread(new MyRunnable());
    
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
        
    System.out.println("Is t1 Alive " + t1.isAlive());
    System.out.println("Is t2 Alive " + t2.isAlive());
    System.out.println("Is t3 Alive " + t3.isAlive());	
    System.out.println("Is t4 Alive " + t4.isAlive());
    System.out.println("Is t5 Alive " + t5.isAlive());
    try {
      t1.join();
      t2.join();
      t3.join();
      t4.join();
      t5.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
        
    System.out.println("Is t1 Alive " + t1.isAlive());
    System.out.println("Is t2 Alive " + t2.isAlive());
    System.out.println("Is t3 Alive " + t3.isAlive());
    System.out.println("Is t4 Alive " + t4.isAlive());
    System.out.println("Is t5 Alive " + t5.isAlive());

    System.out.println("Now start further processing");
  }
}
Output
Is t1 Alive true
In run method --Thread-2
In run method --Thread-0
In run method --Thread-3
Is t2 Alive true
Is t3 Alive true
Is t4 Alive true
Is t5 Alive true
In run method --Thread-4
In run method --Thread-1
Is t1 Alive false
Is t2 Alive false
Is t3 Alive false
Is t4 Alive false
Is t5 Alive false
Now start further processing

As you can see “Now start further processing” message is now displayed only after all the five threads have finished executing. With isAlive() methods after the join() methods it can be verified that the threads are terminated.

Related Posts

That's all for the topic isAlive() And join() Methods in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

Livelock in Java Multi-Threading

In a multi-threaded environment a thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread then a livelock may happen if two or more threads are busy responding to the action of each other and unable to make further progress in the process.

If we take example of three threads where-

  1. Thread-1 is acting on a response from Thread-2
  2. Thread-2 is acting on a response from Thread-3
  3. Thread-3 is acting on a response from Thread-1

So these three threads are busy responding to the action of each other thus unable to make any progress because of livelock.

How livelock is different from deadlock

In case of livelock, just like deadlock, threads don’t make any progress but they are not blocked as the case with deadlock. Threads are active but they are busy responding to each other thus not making any progress.

Java livelock example

In the example there are two threads for customer and shop, customer is waiting for the order to be shipped before paying money where as shop is willing to ship order only after getting amount. So both threads are responding to event but busy there itself unless event condition is fulfilled.

public class ThreadLiveLock {
  static final Customer customer = new Customer();
  static final Shop shop = new Shop();
  public static void main(String[] args) {
    Thread thread1 = new Thread(new Runnable() {
      @Override
      public void run() {
        customer.payMoney(shop);	
      }
    });
    
    Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        shop.shipOrder(customer);	
      }
    });

    thread1.start();
    thread2.start();
  }
}

class Customer{
  private boolean paid = false;
  public void payMoney(Shop shop){
    while(!shop.isOrderShipped()){
      System.out.println("waiting for order");
      try {
        Thread.sleep(1000);
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }
    }
    setPaid(true);
  }
  public boolean isPaid() {
    return paid;
  }
  public void setPaid(boolean paid) {
    this.paid = paid;
  }
}

class Shop{
  private boolean orderShipped = false;
  public void shipOrder(Customer customer){
    while(!customer.isPaid()){
      System.out.println("waiting for money");
      try {
        Thread.sleep(1000);
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }			
    }
    setOrderShipped(true);
  }

  public void setOrderShipped(boolean orderShipped) {
    this.orderShipped = orderShipped;
  }

  public boolean isOrderShipped() {
    return orderShipped;
  }
}
Output
waiting for order
waiting for money
waiting for money
waiting for order
waiting for order
waiting for money
waiting for money
waiting for order
Related Posts

That's all for the topic Livelock in Java Multi-Threading. If something is missing or you have something to share about the topic please write a comment.


You may also like

Thread Starvation in Java

In a multi-threaded environment access to shared resources is synchronized so that at any given time only a single thread can enter a synchronized context. Theoretically all the threads trying to gain access to a synchronized block or method should get some CPU time periodically but in practice that may not happen. If a thread is unable to gain regular access to shared resources and is unable to make progress it is called thread starvation in Java multi-threading.

Why does thread starvation happen

Thread starvation may happen because of the following reasons.
  1. Suppose an object has a synchronized method that requires some heavy processing and takes long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
  2. Threads with higher priority are scheduled to run first and taking all the CPU time causing the thread with minimum priority to keep on waiting to be scheduled to run.
  3. In a synchronized context even if wait method is used to relinquish object’s lock, one of the waiting thread never gets a chance to enter the synchronized context as some other threads are notified and scheduled to run.

Thread starvation Java Example

Let us try to create a scenario when thread starvation in Java may happen using the reasons as stated above.

In the code thread t1 has been assigned the maximum thread priority and it calls the synchronized method thrice. Where as thread t2 has been assigned the minimum thread priority and it calls the synchronized method only once but it has to wait for all the three calls of thread t1 to execute the synchronized method.

class MyRunnable implements Runnable{
  ThreadDemo td;
  MyRunnable(ThreadDemo td){
    this.td = td;
  }
  @Override
  public void run() {
    td.testMethod();
    td.testMethod();
    td.testMethod();
  }	
}

class AnotherRunnable implements Runnable{
  ThreadDemo td;
  AnotherRunnable(ThreadDemo td){
    this.td = td;
  }
  @Override
  public void run() {
    td.testMethod();
  }	
}

public class ThreadDemo {
  public synchronized void testMethod(){
    try {
      System.out.println("Doing some heavy processing for thread " + 
        Thread.currentThread().getName());
      Thread.sleep(300);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
	
  public static void main(String[] args) {		
    ThreadDemo td = new ThreadDemo();
    Thread t1 = new Thread(new MyRunnable(td), "t1");
    Thread t2 = new Thread(new AnotherRunnable(td), "t2");

    t1.setPriority(Thread.MAX_PRIORITY);
    t2.setPriority(Thread.MIN_PRIORITY);

    t1.start();
    t2.start();
  }
}
Output
Doing some heavy processing for thread t1
Doing some heavy processing for thread t1
Doing some heavy processing for thread t1
Doing some heavy processing for thread t2
Related Posts

That's all for the topic Thread Starvation in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

Deadlock in Java With Examples

In a multi-threaded environment there may come a situation when one thread is waiting for a resource that is locked by another thread, which in turn is waiting for another thread and so on until this dependency loops back to the first waiting thread. Thus all the threads are waiting for each other to release the resources to make any further progress and blocked forever in the process. This scenario is called deadlock in multi-threading.

Deadlock example

To explain deadlock in Java we can take a simple scenario of two threads Thread1 and Thread2, where Thread1 holds a lock on obj1 and waiting to acquire a lock on obj2. At the same time Thread2 has a lock on obj2 and waiting to acquire lock on obj1. Here both threads are blocked in a circular loop where Thread1 is waiting to acquire lock on obj2 and Thread2 is waiting to acquire lock on obj1 thus creating a deadlock.

Deadlock in Java

Deadlock in Java scenarios

You may get deadlock in Java because of the improper use of the synchronized keyword. Scenarios when deadlock may happen are as follows.

  1. Nested synchronized blocks with reverse ordering of objects.
  2. Calling one synchronized method from another where methods are not using the same object to synchronize.

Deadlock in Java example

First example shows the scenario when there are nested synchronized blocks with reverse ordering of objects.

class ThreadA implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadA(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj1){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      synchronized(obj2){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      }
    }       
  }  
}

class ThreadB implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadB(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj2){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      synchronized(obj1){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      }
    }   
  }
}

public class DLDemo {
  public static void main(String[] args) {
    Object obj1 = new Object();
    Object obj2 = new Object();
    Thread t1 = new Thread(new ThreadA(obj1, obj2));
    Thread t2 = new Thread(new ThreadB(obj1, obj2));
    t1.start();
    t2.start();
  }
}
Output
Thread-0 acquired obj1 lock
Thread-1 acquired obj2 lock

In ThreadA’s run method synchronization is first done on obj1 and later on obj2. In ThreadB’s run method synchronization is reversed, it is first done on obj2 and later on obj1. That may result in a deadlock where t1 gets a lock on obj1 and waiting to acquire a lock on obj2. At the same time obj2 has acquired a lock on obj2 and waiting to acquired a lock on obj1.

Another deadlock Java example shows the scenario where one synchronized method is called from another.

public class DLDemo {
  public synchronized void method1(DLDemo obj){
    System.out.println(Thread.currentThread().getName() + " In Method1");
    try {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    //Calling another synchronized method
    obj.method2(this);
  }
		 	 
  public synchronized void method2(DLDemo obj2){
    System.out.println("In Method2");
  }

  public static void main(String[] args) {
    DLDemo obj1 = new DLDemo();
    DLDemo obj2 = new DLDemo();
		
    new Thread(new Runnable() {
      public void run() { obj1.method1(obj2); }
    }).start();

    //Thread 2  
    new Thread(new Runnable() {
      public void run() { obj2.method1(obj1); }
    }).start();
  }
}
Output
Thread-0 In Method1
Thread-1 In Method1

In the code there are two instances of DLDemo class, one thread calls the synchronized method method1 using obj1 and another thread calls it using obj2. Which means Thread1 holds a lock on obj1 and Thread2 holds a lock on obj2.

With in the synchronized method method1 there is a call to another synchronized method method2, both of the threads are trying to call method2 with the object whose lock is held by another object thus leading to a deadlock.

How to avoid deadlock in Java

With multi-threading programming deadlock may occur and there is no language support as such to prevent deadlocks. You will have to write your code used by multiple threads carefully to avoid deadlocks. Here we’ll go through the scenarios shown above and see how deadlocks can be avoided in those scenarios.

1. As shown in the previous scenarios one of the reason for the deadlock in Java is the way locks are acquired, if you have nested synchronization then you can acquire the object locks in the same order rather than in reverse order for both threads.

Changed nested synchronization code

class ThreadA implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadA(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj1){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
        synchronized(obj2){
          System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
        }
    }       
  }  
}

class ThreadB implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadB(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj1){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      synchronized(obj2){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      }
    }   
  }
}
Output
Thread-0 acquired obj1 lock
Thread-0 acquired obj2 lock
Thread-1 acquired obj1 lock
Thread-1 acquired obj2 lock

As you can see from the output now the deadlock is avoided.

2. Using synchronized block to minimize the synchronization to the critical section code only will also help in avoiding the deadlock in Java.

In the second scenario rather than synchronizing the whole method synchronized block can be used.

public class DLDemo {
  public void method1(DLDemo obj){
    System.out.println(Thread.currentThread().getName() + " In Method1");
    try {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    synchronized(this){
      //Calling another synchronized method
      obj.method2(this);
    }
  }
		  
  public void method2(DLDemo obj2){
    System.out.println("In Method2");
    synchronized(this){
      System.out.println("In Method2 synchronized block");
    } 
  }

  public static void main(String[] args) {
    DLDemo obj1 = new DLDemo();
    DLDemo obj2 = new DLDemo();
    
    new Thread(new Runnable() {
      public void run() { obj1.method1(obj2); }
    }).start();

    //Thread 2  
    new Thread(new Runnable() {
      public void run() { obj2.method1(obj1); }
    }).start();
  }
}

3- By using static synchronization in Java. If two object instances are used two threads using two separate objects can still enter a synchronized method or block with their separate object locks. Static synchronization helps in this case because the lock will be acquired at the class level then.

How to debug a deadlock in Java

Detecting a deadlock in Java is not easy, even logs may be of little help. If you observe that your multi-threaded code is not performing as well as it was then it may be due to a deadlock and best thing is to get a thread dump of the application and analyze it.

You can use jstack utility to get a thread dump by providing the pid of the Java application. That pid can be obtained by running jps command. For example, if I run the program where deadlock was created due to nested synchronization, then I can get the thread dump using following steps.

1- By using jps command I can get the pid of the Java application.

Jps

5968
7408 DLDemo
13960 Jps

2- Run the jstack command with the pid as argument.

Jstack 7408

3- Get the thread dump and analyze it. Here some of the relevant portion of the thread dump is displayed.

"Thread-1" #11 prio=5 os_prio=0 tid=0x000000001b3e1000 nid=0x145c waiting for monitor entry [0x000000001bade000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.knpcode.ThreadB.run(DLDemo.java:33)
        - waiting to lock <0x00000000d5bfaff0> (a java.lang.Object)
        - locked <0x00000000d5bfb000> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)

"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001b3e0000 nid=0x379c waiting for monitor entry [0x000000001b9de000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.knpcode.ThreadA.run(DLDemo.java:15)
        - waiting to lock <0x00000000d5bfb000> (a java.lang.Object)
        - locked <0x00000000d5bfaff0> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)



"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000004d4c800 nid=0x2b34 in Object.wait() [0x000000001acee000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5b88ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x00000000d5b88ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000004d42000 nid=0x6cc in Object.wait() [0x000000001abef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5b86b68> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Unknown Source)
        at java.lang.ref.Reference.tryHandlePending(Unknown Source)
        - locked <0x00000000d5b86b68> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000004d47868 (object 0x00000000d5bfaff0, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000004d4a0f8 (object 0x00000000d5bfb000, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.knpcode.ThreadB.run(DLDemo.java:33)
        - waiting to lock <0x00000000d5bfaff0> (a java.lang.Object)
        - locked <0x00000000d5bfb000> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)
"Thread-0":
        at com.knpcode.ThreadA.run(DLDemo.java:15)
        - waiting to lock <0x00000000d5bfb000> (a java.lang.Object)
        - locked <0x00000000d5bfaff0> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)

Found 1 deadlock.
Related Posts

That's all for the topic Deadlock in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like