Showing posts with label Java multithreading. Show all posts
Showing posts with label Java multithreading. Show all posts

Friday, April 26, 2024

Printing Numbers in Sequence Using Threads Java Program

This post shows how you can print numbers in sequence using three threads in Java. If there are three threads thread1, thread2 and thread3 then numbers should be printed alternatively by these threads like this.

thread1 - 1
thread2 - 2
thread3 – 3
thread1 - 4
thread2 - 5
thread3 – 6
...
...
...

Print numbers in sequence using three threads in Java

While printing numbers in sequence using threads trick is to use modulo division to check which thread can print the number and which threads are to be blocked waiting.

Each thread is assigned one of the numbers 0, 1 and 2. Each number is divided by 3 (number of threads), remainder will be any one of these numbers 0, 1 or 2. That is what is checked; if (remainder = number assigned to thread) only then thread can work otherwise it goes into waiting state.

class SharedPrinter{
  int number = 1;
  int numOfThreads;
  int numInSequence;
  SharedPrinter(int numInSequence, int numOfThreads){
    this.numInSequence = numInSequence;
    this.numOfThreads = numOfThreads;
  }
  public void printNum(int result){
    synchronized(this) {
      while (number < numInSequence - 1) {
        while(number % numOfThreads != result){
          try {
            this.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        System.out.println(Thread.currentThread().getName() + " - " + number++);
        this.notifyAll();
      }
    }
  }
}
class SeqRunnable implements Runnable{
  SharedPrinter sp;
  int result;
  static Object sharedObj = new Object();
  SeqRunnable(SharedPrinter sp, int result){
    this.sp = sp;
    this.result = result;
  }
  @Override
  public void run() {
    sp.printNum(result);
  }
}
public class SeqNumber {
  final static int NUMBERS_IN_SEQUENCE = 10;
  final static int NUMBER_OF_THREADS = 3;
  public static void main(String[] args) {
    // Shared object
    SharedPrinter sp = new SharedPrinter(NUMBERS_IN_SEQUENCE, NUMBER_OF_THREADS);
    // Creating 3 threads
    Thread t1 = new Thread(new SeqRunnable(sp, 1), "Thread1");
    Thread t2 = new Thread(new SeqRunnable(sp, 2), "Thread2");
    Thread t3 = new Thread(new SeqRunnable(sp, 0), "Thread3");

    t1.start();
    t2.start();
    t3.start();
  }
}

Output

Thread1 - 1
Thread2 - 2
Thread3 - 3
Thread1 - 4
Thread2 - 5
Thread3 - 6
Thread1 - 7
Thread2 - 8
Thread3 - 9
Thread1 - 10

That's all for this topic Printing Numbers in Sequence Using Threads Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. How to Run Threads in Sequence in Java
  2. Print Odd-Even Numbers Using Threads And wait-notify Java Program
  3. Producer-Consumer Java Program Using ArrayBlockingQueue
  4. How to Create Deadlock in Java
  5. Race condition in Java multi-threading

You may also like-

  1. Converting String to Enum Type in Java
  2. Connection Pooling Using C3P0 in Java
  3. Java Program to Find First Non-Repeated Character in a Given String
  4. How to Convert String to Date in Java
  5. Java Multithreading Interview Questions And Answers
  6. How and Why to Synchronize ArrayList in Java
  7. BigDecimal in Java With Examples
  8. Introduction to Hadoop Framework

Saturday, September 10, 2022

Producer-Consumer Java Program Using volatile

Producer-consumer problem using multiple threads in Java is a frequently asked Java Multithreading Interview Questions And Answers. Though there are many ways to do it like-

But a simple way to write Producer-consumer Java program, if you are using one writer thread and one or more reader thread, is to use volatile keyword.

Producer consumer program in Java using volatile

Here logic is to use a volatile boolean flag which steers the logic and makes sure that value is put in the queue only after the previous value is consumed. Here two threads are created one calls the produce method and another consume. In consume method flag is assigned the value false, that is the trigger for the thread calling the produce method to come out of sleep and put another value.

In consume method busy spinning thread is used which loops continuously until the condition is met.

First let’s see what will happen if volatile keyword is not used with the boolean variable flag. In that case it may happen that producer thread sets the flag as true but that value is cached locally and current value of the flag variable is not visible to another thread. That will result in consumer thread getting in an endless busy spinning causing deadlock.

ProducerConsumer class

 
public class ProducerConsumer {
  private int value = 0;
  private boolean flag = false;
  public void produce(Queue<Integer> sharedListObj) {
    // while flag is true put thread to sleep
    while (flag) {
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
     
    sharedListObj.add(++value);
    System.out.println("Thread " + Thread.currentThread().getName() + 
    " putting " + value);
    flag = true;
  }
  public int consume(Queue<Integer> sharedListObj) {
    int j = 0;
    while (!flag) j++;    
    System.out.println("Getting from queue ");
    int value = sharedListObj.remove();
    flag = false;
    System.out.println("Thread " + Thread.currentThread().getName() + 
    " Consuming " + value);
    return value;
  }
}

ProducerConsumerDemo

 
import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerDemo {
  public static void main(String[] args) {
    Queue<Integer> sharedListObj = new LinkedList<Integer>();
    ProducerConsumer producerConsumer = new ProducerConsumer();
    new Thread(new Runnable() {         
      @Override
      public void run() {
         for(int i = 0; i < 5; i++){
             producerConsumer.produce(sharedListObj);
         }
      }
    }, "ProducerThread").start();
         
    new Thread(()-> {
       for(int i = 0; i < 5; i++){
           producerConsumer.consume(sharedListObj);
       }

    }, "ConsumerThread").start();        
  }
}

Output

 
Thread ProducerThread putting 1
Getting from queue 
Thread ConsumerThread Consuming 1
Thread ProducerThread putting 2

When I execute it, I get a deadlock after producing and consuming the first value.

Changing to volatile

Changing flag variable to volatile does the trick, now it is ensured that value of flag won’t be cached locally. It is always read from the main memory.

public class ProducerConsumer {
  private int value = 0;
  private volatile boolean flag = false;
  public void produce(Queue<Integer> sharedListObj) {
    // while flag is true put thread to sleep
    while (flag) {
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
         
    sharedListObj.add(++value);
    System.out.println("Thread " + Thread.currentThread().getName() + 
    " putting " + value);
    flag = true;
  }
  public int consume(Queue<Integer> sharedListObj) {
    int j = 0;
    while (!flag) j++;

    System.out.println("Getting from queue ");
    int value = sharedListObj.remove();
    flag = false;
    System.out.println("Thread " + Thread.currentThread().getName() + 
    " Consuming " + value);
    return value;
  }
}

Output

Thread ProducerThread putting 1
Getting from queue 
Thread ConsumerThread Consuming 1
Thread ProducerThread putting 2
Getting from queue 
Thread ConsumerThread Consuming 2
Thread ProducerThread putting 3
Getting from queue 
Thread ConsumerThread Consuming 3
Thread ProducerThread putting 4
Getting from queue 
Thread ConsumerThread Consuming 4
Thread ProducerThread putting 5
Getting from queue 
Thread ConsumerThread Consuming 5

That's all for this topic Producer-Consumer Java Program Using volatile. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Volatile Keyword in Java With Examples
  2. Race Condition in Java Multi-Threading
  3. Setting And Getting Thread Name And Thread ID in Java
  4. Print Odd-Even Numbers Using Threads And Semaphore Java Program
  5. How to Run Threads in Sequence in Java

You may also like-

  1. Lock Striping in Java Concurrency
  2. AtomicLong in Java With Examples
  3. Callable and Future in Java With Examples
  4. Convert int to String in Java
  5. Java Program to Convert a File to Byte Array
  6. How to Read File From The Last Line in Java
  7. Java Concurrency Interview Questions And Answers
  8. instanceof Operator in Java With Examples

Friday, August 26, 2022

Java Multithreading Tutorial

This Java multithreading tutorial gives an overview of multithreading in Java, how thread is created and executed, how thread-based multitasking is different from process-based multitasking and how to facilitate inter-thread communication.


Multi-tasking – Thread and Process

Multi-tasking as the name suggests means performing multiple tasks at the same time. Operating systems do support multi-tasking for example you would be coding in Java using your favorite IDE while listening to songs in a player and chatting with your team member to clear some doubts about functionality. So at the same time there are at least 3 processes running IDE, player and a messenger. This is an example of process-based multitasking where more than two programs are running concurrently. In process-based multitasking, a program is the smallest unit of execution.

In thread-based multitasking a single program has two or more threads that can run concurrently. In thread-based multitasking, the thread is the smallest unit of execution. For example in your IDE. Building workspace task is going on in background while you are still writing code because these two tasks are performed by two separate threads.

Multi-threading in Java

Java programming language provides in-built support for multithreaded programming. To create a thread in Java you can use any of the following mechanism-

  1. Creating thread by extending the Thread class
  2. Creating thread by implementing the Runnable interface

Every thread created in Java is an object of Thread class. The code that has to be executed by a thread is provided inside the run method. Whether you implement Runnable interface or extend Thread class you need to override run() method and provide the code.

Thread creation example by implementing Runnable interface

class MyThread implements Runnable{
  @Override
  public void run() {
    System.out.println("In run method of MyThread- " 
      + Thread.currentThread().getName());    
  }    
}

public class ThreadDemo {
  public static void main(String[] args) { 
    System.out.println("In main method- " + Thread.currentThread().getName()); 
    // Passing runnable instance
    Thread thread = new Thread(new MyThread(), "MyThread");
    // Calling start method
    thread.start();
  }
}

Output

In main method- main
In run method of MyThread- MyThread

Thread creation example by extending Thread class

Same example when Thread class is extended. Since MyThread is already of type Thread so start() method is called directly using MyThread instance.

class MyThread extends Thread{
  @Override
  public void run() {
    System.out.println("In run method of MyThread- " 
      + Thread.currentThread().getName());    
  }    
}

public class ThreadDemo {
  public static void main(String[] args) { 
    System.out.println("In main method- " + Thread.currentThread().getName()); 
    // Calling start method
    new MyThread().start();
  }
}

Some of the important points about Java multithreading based on these two examples are as follows-

  • run() method has to be overridden, inside run() method you have to provide the functionality that is executed by the thread.
  • After creating thread instance you need to call start method on that thread. Once the thread is scheduled to start run() method will be implicitly called you don’t need to call run() method yourself. Refer What if run() Method Called Directly Instead of start() Method - Java Multi-Threading to know what happens when run() method is called directly.
  • When a Java program is executed one thread starts running immediately that thread is known as main thread in Java. Other threads are spawned from the main thread.

Types of threads

In Java multithreading there are two types of threads.

  1. User threads- Threads which are created to perform tasks related to the application where these threads are spawned.
  2. Daemon threads- Daemon threads are the thread that run in background to perform some tasks for the program as long as the program is running. Daemon threads in Java are suitable for performing general tasks which are not integral part of the application.

Lifecycle of a thread in Java

Java thread cycle is as follows-

  • New state- When a thread is created either by extending Thread class or implementing Runnable interface it is in "New State".
  • Runnable state- When start() method is called on the thread object, that schedules the thread to begin execution when it gets CPU cycle. This thread state is called Runnable.
  • Blocked state- A thread in the blocked state is waiting to acquire a lock so that it can enter a synchronized block/method.
  • Waiting state- A thread that is waiting indefinitely for another thread to perform a particular action is in the waiting state. A thread goes to waiting state duw to calling one of the following methods.
    • Object.wait with no timeout
    • Thread.join with no timeout
    • LockSupport.park
  • Timed_Waiting- A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state. A thread is in the timed waiting state due to calling one of the following methods
    • Thread.sleep
    • Object.wait with timeout
    • Thread.join with timeout
    • LockSupport.parkNanos
    • LockSupport.parkUntil
  • Terminated- A thread that has completed execution is in terminated state.

Refer post Thread States (Thread Life Cycle) in Java Multi-Threading to know more about thread states with examples.

Advantages of Java multi-threading

  1. Multithreading helps you to keep idle time to a minimum as two or more threads are executed concurrently to maximize CPU utilization. With multiple threads one of the thread can execute while another is waiting for some resource.
  2. Thread-based multitasking has less overhead than the process-based multitasking.
  3. Multiple threads share the same address space with in a process saving memory requirement.
  4. Since threads are light weight so context switching from one thread to another is inexpensive.
  5. Since multiple threads are part of the same process so inter-thread communication is also inexpensive.

That's all for this topic Java Multithreading Tutorial. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Thread Priorities in Java Multi-Threading
  2. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  3. Synchronization in Java - Synchronized Method And Block
  4. Difference Between sleep And wait in Java Multi-Threading
  5. Java ThreadLocal Class With Examples

You may also like-

  1. Difference Between equals() Method And equality Operator == in Java
  2. strictfp in Java
  3. Garbage Collection in Java
  4. CallableStatement Interface in Java-JDBC
  5. Removing Spaces Between Words in a String Java Program
  6. Spring Transaction Management Example - @Transactional Annotation and JDBC
  7. Magic Methods in Python With Examples
  8. Java Multithreading Interview Questions And Answers

Thursday, June 16, 2022

Java ThreadLocal Class With Examples

Usually when there are multiple threads sharing an object we need to synchronize the critical section of the code in order to make it thread safe. ThreadLocal class in Java provides another way of thread-safety apart from synchronization.


How ThreadLocal class provides thread safety

ThreadLocal class in Java provides thread-local variables where each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. Since each and every thread has its own copy of the object so explicit synchronization is not needed to provide thread safety.

How to create a ThreadLocal variable

Let's see how threadlocal variable is created and what all methods are provided by ThreadLocal class in Java to get and set value of a ThreadLocal variable.

Creating a ThreadLocal variable

private static final ThreadLocal<String> threadLocalVar = new ThreadLocal<String>();

Here I have created a ThreadLocal variable called threadLocalVar which will store a String value.

Setting and accessing the value

Once an instance of ThreadLocal class is created, its set method can be used to set a value-

threadLocalVar.set("This is a thread local variable");

get method is used to read the value, note that get method returns the value in the current thread's copy of this thread-local variable.

threadLocalVar.get();

ThreadLocal variable can be accessed globally by a thread

One interesting point about Java ThreadLocal variable is the global access. Any thread local variable is global to a thread. It can be accessed anywhere from the thread. If, from a thread several methods residing in different classes are called, thread local variable will be visible to all those methods. There is no need to pass the thread local variable as a parameter.

ThreadLocal variable is local to a thread

At the same time any threadlocal variable is local to a thread. If there are 10 threads spawned all the 10 threads will have their own thread local variable. One thread can not access/modify other thread's Thread Local variables.

Initial Value of a ThreadLocal variable

ThreadLocal class in Java provides a method called initialValue() which can be used to provide initial value to a created ThreadLocal variable.

// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
  @Override 
  protected Integer initialValue() {
    return nextId.getAndIncrement();
  }
};

Note that ThreadLocal class is modified in Java 8 and a new method withInitial is added to it with a general form -

public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)

Here Supplier is a functional interface with one method get() and using lambda expression implementation of this method can be provided. If we use withInitial method, what we did for initialValue() method -

private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
  @Override 
  protected Integer initialValue() {
    return nextId.getAndIncrement();
  }
};

Can be done like this-

 threadId = ThreadLocal.withInitial(()-> {return nextId.getAndIncrement();});

Java ThreadLocal class usage examples

Now when we know what is a ThreadLocal class and how it can be used to create variables which are thread safe, let's see two use cases where it can be used.

  1. When we have a requirement to associate state with a thread (e.g., a user ID or Transaction ID). That usually happens with a web application that every request going to a servlet has a unique transactionID associated with it.

    Example code for this requirement

    // This class will provide a thread local variable which
    // will provide a unique ID for each thread
    class ThreadId {
      // Atomic integer containing the next thread ID to be assigned
      private static final AtomicInteger nextId = new AtomicInteger(0);
    
      // Thread local variable containing each thread's ID
      private static final ThreadLocal<Integer> threadId =
        ThreadLocal.<Integer>withInitial(()-> {return nextId.getAndIncrement();});
    
      // Returns the current thread's unique ID, assigning it if necessary
      public static int get() {
        return threadId.get();
      }
    }
    
    // In this class thread's run method is executed
    class MyClass implements Runnable{
      @Override
      public void run() {
        System.out.println("Thread " + Thread.currentThread().getName() 
        + " Value - " +  ThreadId.get());
      }
    }
    
    public class ThreadLocalDemo {  
      public static void main(String[] args) {
        MyClass mc1 = new MyClass();
        Thread thread1 = new Thread(mc1, "Thread-1");
        Thread thread2 = new Thread(mc1, "Thread-2");
        Thread thread3 = new Thread(mc1, "Thread-3");
        thread1.start();
        thread2.start();
        thread3.start();
      }
    }
    

    Output

    Thread Thread-1 Value - 0
    Thread Thread-2 Value - 1
    Thread Thread-3 Value - 2
    

    It can be seen how each thread has a unique ID.

  2. Another use case where ThreadLocal is useful is when we want to have a thread safe instance and we don't want to use synchronization as the performance cost with synchronization is more. One such case is when SimpleDateFormat is used. Since SimpleDateFormat is not thread safe so we have to provide mechanism to make it thread safe.

    First let's see how we can use synchronized to achieve that.

    public class DateFormatDemo {
      private DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
      public Date convertStringToDate(String dateString) throws ParseException {
      Date result;
      synchronized(df) {
        result = df.parse(dateString);
      }
      return result;
      }  
    }
    

    Now let's see an example how ThreadLocal can be used by storing separate instance of SimpleDateFormat for each thread.

    public class ThreadLocalDemo1 implements Runnable {
      // threadlocal variable is created
      private static final ThreadLocal<SimpleDateFormat> dateFormat = 
                    new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue(){
          System.out.println("Initializing SimpleDateFormat for - " 
                            + Thread.currentThread().getName() );
          return new SimpleDateFormat("dd/MM/yyyy");
        }
      };
                
      public static void main(String[] args) {
        ThreadLocalDemo1 td = new ThreadLocalDemo1();
        // Two threads are created
        Thread t1 = new Thread(td, "Thread-1");
        Thread t2 = new Thread(td, "Thread-2");
        t1.start();
        t2.start();
      }
    
      @Override
      public void run() {
        System.out.println("Thread run execution started for " 
                          + Thread.currentThread().getName());
        System.out.println("Date formatter pattern is  " 
                         + dateFormat.get().toPattern());
        System.out.println("Formatted date is " 
                         + dateFormat.get().format(new Date()));
      } 
    }
    

    Output

    Thread run execution started for Thread-2
    Thread run execution started for Thread-1
    Initializing SimpleDateFormat for - Thread-2
    Initializing SimpleDateFormat for - Thread-1
    Date formatter pattern is  dd/MM/yyyy
    Date formatter pattern is  dd/MM/yyyy
    Formatted date is 26/07/2015
    Formatted date is 26/07/2015
    

    If you notice here SimpleDateFormat instance is created and initialized for each thread.

Points to note

  1. ThreadLocal class in Java provides another alternative to thread safety, apart from synchronization.
  2. With ThreadLocal each and every thread has its own thread local variable. One thread cannot access/modify other thread's ThreadLocal variables.
  3. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.

That's all for this topic Java ThreadLocal Class With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between yield and sleep in Java Multi-Threading
  2. What if run() Method Called Directly Instead of start() Method - Java Multi-Threading
  3. Volatile Keyword in Java With Examples
  4. Is String Thread Safe in Java
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Encapsulation in Java
  2. Difference Between Checked And Unchecked Exceptions in Java
  3. Best Practices For Exception Handling in Java
  4. Interface Static Methods in Java
  5. Method Reference in Java
  6. ConcurrentHashMap in Java With Examples
  7. How ArrayList Works Internally in Java
  8. Print Odd-Even Numbers Using Threads And wait-notify Java Program

Monday, June 13, 2022

What if run() Method Called Directly Instead of start() Method - Java MultiThreading

When we call start() method on the thread it causes the thread state to change to "Runnable". It’s the Java Virtual Machine that calls the run method of that thread to actually start the thread execution, run() method is not called directly. In this post you'll see what happens if run() method is called directly in Java multi-threading.

What if run method is called directly

If run() method is called directly instead of start() method in Java code, run() method will be treated as a normal overridden method of the thread class (or runnable interface). This run method will be executed with in the context of the current thread not in a new thread.

It’s the start() method that spawns a new thread and schedules the thread with the JVM. The JVM will let the newly spawned thread execute run() method when the resources and CPU are ready. So not calling the start method and directly calling the run() method will mean a new thread object is not created and run() method will run as a normal overridden method.

Calling run method directly example

Let’s create a class and spawn two threads and cause some delay in the execution if they are real threads then there will be context switchingwhile one thread is not executing another thread will execute. When start method is not called no new threads are created thus there won’t be any context switching and the execution will be sequential.

public class MyThreadClass extends Thread{
  @Override
  public void run(){
    System.out.println("In run method " + Thread.currentThread().getName());
    for(int i = 0; i < 5 ; i++){
      System.out.println("i - " + i);
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
    
  public static void main(String[] args) {
    MyThreadClass mc1 = new MyThreadClass(“MyThread1”);
    MyThreadClass mc2 = new MyThreadClass();
    mc1.run();
    mc2.run();
  }
}

Output

In run method main
i - 0
i - 1
i - 2
i - 3
i - 4
In run method main
i - 0
i - 1
i - 2
i - 3
i - 4

Here two threads are created and run() method is called directly on the threads rather than calling the start() method. As you can see in the above program there is no context-switching because here threads mc1 and mc2 will be treated as normal object not thread object. Name of the thread is also not printed.

Calling start() method

Now let's change the above program and use the thread's start method rather than directly calling the run() method.

public class MyThreadClass extends Thread{
  @Override
  public void run(){
    System.out.println("In run method " + Thread.currentThread().getName());
    for(int i = 0; i < 5 ; i++){
      System.out.println("i - " + i);
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
    
  public static void main(String[] args) {
    MyThreadClass mc1 = new MyThreadClass();
    MyThreadClass mc2 = new MyThreadClass();
    mc1.start();
    mc2.start();
  }
}

Output

In run method Thread-0
i - 0
In run method Thread-1
i - 0
i - 1
i - 1
i - 2
i - 2
i - 3
i - 3
i - 4
i – 4

Now you can see how context switching is happening and values are printed for both threads concurrently. You can even see the thread name printed now.

Points to note

  • When we call start() method on the thread it causes the thread to begin execution.
  • run() method of the thread is called by the Java Virtual Machine.
  • If we directly call run method it will be treated as a normal overridden method of the thread class (or runnable interface) and it will be executed with in the context of the current thread not in a new thread.

That's all for this topic What if run() Method Called Directly Instead of start() Method - Java MultiThreading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Synchronization in Java - Synchronized Method And Block
  2. Volatile Keyword in Java With Examples
  3. Is String Thread Safe in Java
  4. Livelock in Java Multi-Threading
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. equals() And hashCode() Methods in Java
  2. Fail-Fast Vs Fail-Safe Iterator in Java
  3. Nested Try Statements in Java Exception Handling
  4. Multi-Catch Statement in Java Exception Handling
  5. JVM Run-Time Data Areas - Java Memory Allocation
  6. Constructor Overloading in Java
  7. Zipping Files And Folders in Java
  8. Spring Component Scan to Automatically Discover Beans

Monday, June 6, 2022

Synchronization in Java - Synchronized Method And Block

In this post we'll see how thread synchronization is done using synchronized keyword in Java.

In a multithreaded environment when multiple threads are trying to access a shared resource we need to have some mechanism to ensure that the resource will be used only by one thread at a time. The process by which it is ensured is called synchronization in multi-threading.


How synchronization in Java works

For achieving synchronization in Java concept of monitor is used. Every object created in Java has one associated monitor (mutually exclusive lock). At any given time Only one thread can own the monitor.

The Java programming language provides two basic synchronization idioms using the synchronized keyword.

  • synchronized methods
  • synchronized statements (also known as synchronized blocks).

Before any thread executes the code which is with in a synchronized method (or synchronized block) compiler provides instructions to acquire the lock on the specified object.

When any thread acquires a lock it is said to have entered the monitor. All other threads which need to execute the same shared piece of code (locked monitor) will be suspended until the thread which initially acquired the lock releases it.

Where can we use synchronized keyword in Java

As already stated synchronized keyword can be used with methods or blocks in Java. This can be further divided into use with instance methods and static methods. Which means, we can have four different ways synchronized keyword in Java can be used.

  • instance method
  • An enclosed code block with in an instance method (Synchronized block).
  • static method
  • An enclosed code block with in a static method.

Refer Static Synchronization in Java Multi-Threading to see how to use synchronization with static method and block and why it is needed.

Let's see where and why we should use a specific type of synchronized method or block.

Synchronized Method in Java

We can synchronize a method by adding synchronized keyword within a method signature.

General Form of synchronized instance method

synchronized <returntype> method_name(parameter_list){
  ..
  ..
}

Java synchronized method example

Let's see an example code where first we write the code without synchronizing the method and later we have the same code where method is synchronized.

Here we have a class Message whose object will be shared among threads. In class Message there is a method displayMsg and you want one thread to finish printing the message with in the method then only another thread starts executing the method.

Code when synchronized keyword is not used

// This class' shared object will be accessed by threads
class Message{
 public void displayMsg(String msg){
   System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
   System.out.println("**" + msg); 
   try {
      Thread.sleep(10);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   System.out.println("*");
 }
}
 
class MyClass implements Runnable{
  Thread t;
  Message msg;
  String message;
  MyClass(Message msg, String str){ 
    this.msg = msg;
    this.message = str;
    // creating threads, 4 threads will be created 
    // all sharing the same object msg
    t = new Thread(this);
    t.start();
  }
  @Override
  public void run() {
     msg.displayMsg(message);
  }
}

public class SynchronizedDemo {
  public static void main(String[] args) {
    Message msg = new Message();
    MyClass mc1 = new MyClass(msg, "I");
    MyClass mc2 = new MyClass(msg, "am");
    MyClass mc3 = new MyClass(msg, "not");
    MyClass mc4 = new MyClass(msg, "synchronized");
  }
}

Output

I got the following output, for you output may differ as it depends upon which thread is picked first.

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
**synchronized
Inside displayMsg method Thread-1
**am
Inside displayMsg method Thread-2
**not
**I
*
*
*
*

It can be seen how output is all jumbled, because all the 4 threads share the same object and synchronized keyword is not used to ensure that only single thread has the lock on the object and only that thread can execute the method.

Code when synchronized is used

If we synchronize a method only a single thread will access the method at the given time. In that case the displayMsg() method will look like -

class Message{
  public synchronized void displayMsg(String msg){
    System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
    System.out.print("**" + msg);        
    try {
      Thread.sleep(3);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("*");
  }
}

Output

Inside displayMsg method Thread-0
**I*
Inside displayMsg method Thread-1
**am*
Inside displayMsg method Thread-2
**not*
Inside displayMsg method Thread-3
**synchronized*

Now it can be seen how one thread finishes its execution then only another thread starts its execution of the method. Though which thread is picked first is up to the scheduler that's why the message may not print correctly but the point here is that whichever thread enters the synchronized method that finishes then only the next thread starts its execution.

Please note that a synchronized instance method is synchronized on the instance(object) of the class. So, if a class has more than one object then one thread at a time can enter each object's synchronized method.

Synchronized statement (block) in Java

You don't need to synchronize the whole method, let's say we have a 100 line code method, out of which critical section (shared resource) comprises of 7 lines only then it makes sense to synchronize those 7 lines only rather than the whole method. That way we can improve performance.

synchronized statements must specify the object that provides the intrinsic lock.

General Form of Synchronized statement (synchronized block)

synchronized(object_reference){
  // code block
}

Though it is also possible to synchronize on a string but it is considered a bad idea as "Literal strings within different classes in different packages likewise represent references to the same String object." See this for reference - http://www.javalobby.org/java/forums/t96352.html

Java synchronized block example

If we use the same example used above with synchronized method it can be changed to use synchronized block like this-

//This class' shared object will be accessed by threads
class Message{
  public void displayMsg(String msg){
    System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
    synchronized(this){
      System.out.print("**" + msg);        
      try {
        Thread.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("*");
    }
  }
}

Output

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
Inside displayMsg method Thread-2
Inside displayMsg method Thread-1
**I*
**am*
**not*
**synchronized*

It can be seen from the output how the first print statement is executed by all the threads as that is not inside the synchronized block. After that only a single thread executes at a time and finishes its execution of the synchronized block only then another thread enters the synchronized block.

Drawback of using Synchronization in Java

Synchronization can introduce thread contention, which occurs when two or more threads try to access the same resource simultaneously and cause the Java runtime to execute one or more threads more slowly, or even suspend their execution. Thread Starvation and livelock are forms of thread contention.

That's all for this topic Synchronization in Java - Synchronized Method And Block. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block
  2. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  3. Difference Between ReentrantLock and Synchronized in Java
  4. Deadlock in Java Multi-Threading
  5. ThreadLocal class in Java

You may also like-

  1. Java Multithreading Interview Questions And Answers
  2. Varargs (Variable-length Arguments) in Java
  3. Covariant Return Type in Java
  4. Java Pass by Value or Pass by Reference
  5. Method Reference in Java
  6. Interface Default Methods in Java
  7. How HashMap Works Internally in Java
  8. Count Number of Words in a String Java Program

Monday, May 23, 2022

Thread States (Thread Life Cycle) in Java Multi-Threading

It is important to know the lifecycle of a thread in Java and various states a Java thread can be in. That will give an idea about what happens after creating a thread in Java and after calling the start() method on a thread. In this post we'll see various Thread states in Java multi-threading.

In order to begin execution of the thread's run() method you need to call the start() method on the thread. That is when Java Virtual Machine calls the run method of the thread.

Once scheduled to run by JVM a thread will run when its gets CPU cycle. A thread may be in waiting, blocked or running state after scheduled to run and later transitions to terminated state.

Java thread states

Thread states in Java or the Java thread cycle is as follows.

New state

When a thread is created either by extending Thread class or implementing Runnable interface it is in "New State".

Thread thread1 = new ThreadDemoClass();

When a thread is in "New" state it is not yet scheduled to run.

Runnable state

When start() method is called on the thread object, that causes the thread to begin execution and it's the Java Virtual Machine that calls the run() method of the thread.

Thread thread1 = new ThreadDemoClass();
thread1.start();

This thread state is called Runnable as thread may not start running as soon as the start() method is called. It depends on the native OS when it schedules the thread to start running. A thread starts running when it gets the CPU cycle. A running thread may change state to waiting, blocked, runnable again and terminated.

Blocked state

When a resource is shared among various threads then a thread may go into blocked state as the resource may be used by another thread. In that case a thread has to suspend its execution because it is waiting to acquire a lock.
As example in case of synchronized block where only one thread can enter that block of code.

synchronized (object reference) {   
  //code that uses shared resource 
}  

A thread in Java is also in blocked state when waiting for some IO to complete.

Waiting state

A thread that is waiting indefinitely for another thread to perform a particular action is in the waiting state.
As example A thread is waiting because of a call to wait() or join() method where no time of waiting is specified as parameter.

Timed_Waiting

A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
As exp. A thread is waiting because of a call to wait() or join() method where time of waiting is specified as parameter. Calling sleep(long millis) will also result in a thread entering a TIMED_WAITING state.

Example with Sleep

Thread myThread = new MyThreadClass();
myThread.start();
try {
  myThread.sleep(10000);
} catch (InterruptedException e){
 
}

Terminated

A thread that has exited is in terminated state. This happens when the thread has completed executing the run() method. A thread may also be terminated any time by calling its stop() method (note that Thread.stop() is deprecated and it is inherently unsafe)

thread states in java
Various thread states

Getting thread's state in Java

Thread class has a method getState(), using that method you can get the current state of a thread. This method returns Thread.State enum which has constants for all the above mentioned thread states.

public class ThreadStates {

 public static void main(String[] args) {
  Thread thread = new Thread(new MyThread(), "MyThread");
  displayState("State after creation", thread);
  // Calling start method
  thread.start();
 
  try {
   // sleep method on Main thread 
   Thread.sleep(200);
   displayState("After starting ", thread);
   thread.join();
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  displayState("State after running ", thread);
 }
 
 public static void displayState(String msg, Thread thread){
  System.out.println(msg + "- " + "Thread Name- " + thread.getName() 
     + " State- " +  thread.getState());
 }
}

class MyThread implements Runnable{
  @Override
  public void run() {
    ThreadStates.displayState("State in run method ", Thread.currentThread());
    System.out.println("In run method of MyThread --" + Thread.currentThread().getName());   
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    ThreadStates.displayState("In run method after sleep", Thread.currentThread());  
  }    
}

Output

State after creation- Thread Name- MyThread State- NEW
State in run method - Thread Name- MyThread State- RUNNABLE
In run method of MyThread --MyThread
After starting - Thread Name- MyThread State- TIMED_WAITING
In run method after sleep- Thread Name- MyThread State- RUNNABLE
State after running - Thread Name- MyThread State- TERMINATED

That's all for this topic Thread States (Thread Life Cycle) in Java Multi-Threading . If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Thread Priority in Java Multi-Threading
  2. Can we Start The Same Thread Twice in Java
  3. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  4. Race Condition in Java Multi-Threading
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Interface Default Methods in Java
  2. @FunctionalInterface Annotation in Java
  3. Check if Given String or Number is a Palindrome Java Program
  4. static Method Overloading or Overriding in Java
  5. static Reference to The Non-static Method or Field Error
  6. ConcurrentHashMap in Java With Examples
  7. How HashMap Internally Works in Java
  8. How to Sort an ArrayList in Descending Order in Java

Saturday, May 21, 2022

Thread Starvation in Java Multi-Threading

In any multi-threaded application, where you have multiple threads vying for the access over the shared resources you may come across a situation where a thread (or a bunch of threads) is unable to gain regular access to shared resources and is unable to make progress. This situation is known as thread starvation.

Thread starvation in multi-threading may happen because other "greedy" threads are gaining the lock and access to the shared resource, resulting in a thread (or a bunch of threads) getting starved of access to shared resources and CPU time.

Thread starvation in Java

Some of the reasons why thread starvation may happen in Java-

  • If there is an object providing a synchronized method that requires a lots of processing time. If there is a thread invoking this method quite frequently, other threads that also need to access the synchronized method will be blocked.
  • If there are some higher priority threads those threads will get executed first rather than the threads having lower priority.
  • If you are using wait-notify signalling, then theoretically a thread that is waiting to get access to a shared resource may wait indefinitely if always some other thread is notified and get access to the shared resource.

Thread starvation scenario - Java Example

Let’s see an example in Java where thread starvation scenario is shown.

Here we have a class called ThreadStarveDemo which has a synchronized method displayValues(). Three threads are created which will share an object of class ThreadStarveDemo. There are two classes Display and Display1.

Two thread objects are created of type Display and one thread object of type Display1 is created. While the two thread objects of type Display are given the maximum priority the thread object of type Display1 is given the minimum priority.

In displayValues() method, sleep method of thread class is used to simulate some delay (processing time) and it is called thrice from maximum priority threads to have a scenario that the method is invoked frequently from thread.

class Display implements Runnable{
  private ThreadStarveDemo td;
  Display(ThreadStarveDemo td){
    this.td = td;
  }
  @Override
  public void run() {
    td.displayValues();
    System.out.println("Calling again");
    td.displayValues();
    System.out.println("Calling again");
    td.displayValues();
    //System.out.println("Calling again");       
  }    
}

/**
 * 
 */
class Display1 implements Runnable{
  private ThreadStarveDemo td;
  Display1(ThreadStarveDemo td){
    this.td = td;
  }
  @Override
  public void run() {
    try {
      // introducing some delay
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    td.displayValues();
    //System.out.println("Calling again");       
  }    
}

public class ThreadStarveDemo {
    
  synchronized void displayValues(){
    System.out.println("In ThreadStarveDemo For thread " + 
      Thread.currentThread().getName());
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("For thread " + Thread.currentThread().getName());
    for(int i = 0; i < 3; i++){
      System.out.println("Value of i " + i);
    }        
  }
    
  public static void main(String[] args) {
    ThreadStarveDemo td1 = new ThreadStarveDemo();
    // Creating 3 threads
    Thread thread0 = new Thread(new Display1(td1));
    Thread thread1 = new Thread(new Display(td1));
    Thread thread2 = new Thread(new Display(td1));

    // Setting priorities
    thread1.setPriority(Thread.MAX_PRIORITY);
    thread2.setPriority(Thread.MAX_PRIORITY);
    thread0.setPriority(Thread.MIN_PRIORITY);

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

Output

In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-1
Calling again
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-1
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-0
For thread Thread-0
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-1
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2

Here it can be seen that Thread-0 has to invoke displayValues() method only once but that invocation is delayed by the threads of maximum priority.

Think of same scenario in a multi-threaded application having lots of threads and a synchronized method called from various points in the application. There is a very good chance that thread starvation may happen.

That's all for this topic Thread Starvation in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Race Condition in Java Multi-Threading
  2. Deadlock in Java Multi-Threading
  3. Volatile Keyword in Java With Examples
  4. Is String Thread Safe in Java
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Lock Striping in Java Concurrency
  2. Non-Blocking Algorithms
  3. AtomicInteger in Java With Examples
  4. Executor And ExecutorService in Java With Examples
  5. Wiring Collections in Spring
  6. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
  7. How to Create Immutable Class in Java
  8. static Block in Java

Wednesday, May 18, 2022

Can we Start The Same Thread Twice in Java

What if we start the same thread again in Java is one question you will be confronted with in many Java Multi-threading interview questions. This post tries to answer this question whether you can start the same thread twice or not.

According to Java Docs- https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.html#start() description of start method in the Thread class says-

  • public void start()- Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
    The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
    It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
    Throws: IllegalThreadStateException- If the thread was already started.

Thus a Thread can only be started once and any attempt to start the same thread twice in Java will throw IllegalThreadStateException.

Thread's transition to terminated State

As we saw in Thread States in Java Multi-Threading once a Java thread finishes execution it transitions to terminated (dead) state. Calling start() method on a terminated thread should not be permitted and that's why IllegalThreadStateException is thrown.

Starting a thread twice in Java example

public class ThreadTwiceStart implements Runnable {
  public static void main(String[] args) {
    // creating a thread 
    Thread t = new Thread(new ThreadTwiceStart(), "MyThread");
    t.start();
    // starting the same thread again
    t.start();
  }

  @Override
  public void run() {
    System.out.println("Thread started running " + Thread.currentThread().getName());    
  }
}

Output

Thread started running MyThread
Exception in thread "main" java.lang.IllegalThreadStateException
 at java.lang.Thread.start(Unknown Source)
 at org.netjs.example.ThreadTwiceStart.main(ThreadTwiceStart.java:9)

It can be seen how it has thrown IllegalThreadStateException if an attempt is made to start the same thread again.

If we have to start the same thread again we have to create a new thread object. This code will run fine-

public class ThreadTwiceStart implements Runnable {
  public static void main(String[] args) throws InterruptedException{
    // creating a thread 
    Thread t = new Thread(new ThreadTwiceStart(), "MyThread");
    t.start();
    t.join();       
    t = new Thread(new ThreadTwiceStart(), "MyThread");        
    t.start();
  }

  @Override
  public void run() {
    System.out.println("Thread started running " + Thread.currentThread().getName());    
  }
}

Here a new thread object is created before calling the start method again thus this code will run without throwing any exception.

That's all for this topic Can we Start The Same Thread Twice in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between Thread And Process in Java
  2. Thread States (Thread Life Cycle) in Java Multi-Threading
  3. What if run() Method Called Directly Instead of start() Method - Java Multi-Threading
  4. Race Condition in Java Multi-Threading
  5. Difference Between sleep And wait in Java Multi-Threading

You may also like-

  1. Lambda Expressions in Java 8
  2. Java ReentrantLock With Examples
  3. How to Loop Through a Map in Java
  4. How HashMap Works Internally in Java
  5. Java Program to Find The Longest Palindrome in a Given String
  6. final Vs finally Vs finalize in Java
  7. Marker Interface in Java
  8. Difference Between Abstract Class And Interface in Java

Monday, April 11, 2022

isAlive() And join() Methods in Java Multi-Threading

When we are using multiple threads in our application, we’ll create the threads and call the start() method on these threads. It’s the Java Virtual Machine that calls the run method of this thread when the resources and CPU are ready. Then the thread will execute the run() method and later transition to terminated state.

Suppose you have a scenario where you want to start further processing only when a thread has ended then how will you know that a thread has ended?

Java multi-threading provides two ways to find that–

  • isAlive()
  • join()

isAlive() method in Java

isAlive() method is the member of the Thread class and its general form is–

public final boolean isAlive()

isAlive() method tests if the thread it is called upon is alive or not. A thread is alive if it has been started and not yet terminated. The isAlive() method returns true if the thread upon which it is called is still running, otherwise it returns false.

join() method in Java

Join() method is used when you want to wait for the thread to finish. Its general form is–

public final void join() throws InterruptedException

This method waits until the thread on which it is called terminates. There are three overloaded join functions.

  • public final void join()- Waits indefinitely for this thread to die.
  • public final void join(long millis)-Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
  • public final void join(long millis, int nanos)- Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

Java Example code using join and isAlive()

Let’s say there is a scenario where in a code multiple threads are spawned to do some heavy computation and only when the processing is done a message should be displayed to a user that “Processing is done”.
Now first let’s try to do something like this without using join() method.

class MyRunnableClass implements Runnable{
  @Override
  public void run() {
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }    
}
public class JoinExample {
  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnableClass(), "t1");
    Thread t2 = new Thread(new MyRunnableClass(), "t2");
    Thread t3 = new Thread(new MyRunnableClass(), "t3");
     
    t1.start();
    t2.start();
    t3.start();
        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
        
    /*try {
        t1.join();        
        t2.join();
        t3.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());*/        
    System.out.println("Processing finished");
  }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
Processing finished
t3 i - 0
t1 i - 0
t2 i - 0
t3 i - 1
t1 i - 1
t2 i - 1
t2 i - 2
t1 i - 2
t3 i - 2
t3 i - 3
t1 i - 3
t2 i - 3
t3 i - 4
t1 i - 4
t2 i – 4

Here it can be seen that the message is displayed much before the actual processing has finished.

Now let’s uncomment the code related to join and run the program again.

class MyRunnableClass implements Runnable{
  @Override
  public void run() {
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
public class JoinExample {
  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnableClass(), "t1");
    Thread t2 = new Thread(new MyRunnableClass(), "t2");
    Thread t3 = new Thread(new MyRunnableClass(), "t3");
     
    t1.start();
    t2.start();
    t3.start();
    
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
        
    try {
      t1.join();        
      t2.join();
      t3.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
    
    System.out.println("Processing finished");
  }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
t2 i - 0
t3 i - 0
t1 i - 0
t1 i - 1
t2 i - 1
t3 i - 1
t3 i - 2
t1 i - 2
t2 i - 2
t1 i - 3
t2 i - 3
t3 i - 3
t2 i - 4
t3 i - 4
t1 i - 4
t1 Alive - false
t2 Alive - false
t3 Alive - false
Processing finished

Now see how message is displayed only when the processing is actually finished and all the threads are terminated. The second print statements using isAlive() method confirms that the threads are not running any more.

That's all for this topic isAlive() And join() Methods in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between sleep And wait in Java Multi-Threading
  2. Creating a Thread in Java
  3. Synchronization in Java - Synchronized Method And Block
  4. Race Condition in Java Multi-Threading
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Creating Custom Exception Class in Java
  2. Interface Static Methods in Java
  3. Fail-Fast Vs Fail-Safe Iterator in Java
  4. Java Lambda Expression And Variable Scope
  5. Find All Permutations of a Given String Java Program
  6. Abstraction in Java
  7. Java ReentrantReadWriteLock With Examples
  8. Bean Scopes in Spring With Examples

Friday, April 8, 2022

Inter-thread Communication Using wait(), notify() And notifyAll() in Java

Java provides inter-thread communication using the following methods of the Object class.

  • wait()
  • notify()
  • notifyAll()

wait(), notify() and notifyAll() methods in Java

These methods wait(), notify() and notifyAll() are implemented as final method in the Object class thus available to all the classes, as Object class is the super class of all the classes in Java.

Another important point about wait(), notify() and notifyAll() methods in Java is that they can only be called from a synchronized context, as these methods are about releasing the monitor and acquiring it again. Threads acquire monitor(lock) when entering a synchronized method (or block) so it makes sense to call them from synchronized context.

Refer Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block to see why these methods must be called from a synchronized context.


wait() method in Java

Wait method tells the current thread (thread which is executing code inside a synchronized method or block) to give up monitor and go to sleep, until another thread invokes the notify() or notifyAll() method for this object.

General form of wait method in Java

public final void wait() throws InterruptedException

There are two more overloaded wait methods

public final void wait(long timeout) throws InterruptedException

Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.

public final void wait(long timeout, int nanos) throws InterruptedException

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.

Generally you'll use code similar to as given below for calling wait method.

synchronized (obj) {
  while (condition not true){
    obj.wait();
  }
}

notify() method in Java

Wakes up a single thread that is waiting on this object's monitor. If more than one threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.

Note that the thread which comes out of waiting because of the notify() method will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread just changes to the runnable state and it is ready to be scheduled again. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object. The awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

When awakened thread(thread which has come out of waiting because of notify() method) gains control of the object, all its synchronization claims on the object are restored to the situation as of the time that the wait method was invoked that is on return from the wait method, the synchronization state of the object and of thread is exactly as it was when the wait method was invoked.

Generally you'll use code similar to as given below for calling notify method.

synchronized (obj) {
  while (condition not true){
    obj.wait();
  }
  // When condition holds true
  ..
  ..
  obj.notify();
}

notifyAll() method in Java

Wakes up all the threads that called wait() on the same object. As explained in notify() any one of the threads will be granted access to the object.

Generally you'll use code similar to as given below for calling notifyAll method.

synchronized (obj) {
  while (condition not true){
    obj.wait();
  }
  // When condition holds true
  ..
  ..
  obj.notifyAll();
}

What is Spurious Wakeup

Once wait is called on an object the thread that is currently executing with in the synchronized context waits until notify() or notifyAll() method is called. But there is a possibility that a waiting thread resumes again even when notify() or notifyAll() are not called (this will rarely occur in practice). This is known as spurious wakeup in Java.

To guard against spurious wakeup the recommendation is that call to wait() method should be with in a loop that checks the condition on which the thread is waiting.

synchronized (obj) {
  while (condition does not hold)
    obj.wait(timeout);
    ... // Perform action appropriate to condition
}

Read more about spurious wakeup in the wait method of the Java docs of Object class- http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html

Producer-Consumer example using wait, notify in Java

Let's see one of the oft mentioned example of producer and consumer implemented with two threads, where producer thread produces a number, puts it in a list and then consumer thread gets that number out of the list. Since a shared list is used between these two threads, so to make sure that both threads work in tandem wait() and notify() methods are used for inter-thread communication.

class Producer implements Runnable{
  List<Integer> sharedListObj;
  Producer(List<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {
    int i = 0;
    while(true){
      synchronized (sharedListObj) {
        // While condition as mandated to avoid spurious wakeup
        while(sharedListObj.size() >= 1){
          try {
            sharedListObj.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        // Putting value in the list
        System.out.println("Adding to queue - " + Thread.currentThread().getName() + " " + ++i);
        sharedListObj.add(i);
        sharedListObj.notify();    
        // To get out of while(true) loop, putting
        // only 5 values
        if(i > 4) break;
      }
    }
  }            
}

class Consumer implements Runnable{
  List<Integer> sharedListObj;
  Consumer(List<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {    
    while(true){
      synchronized (sharedListObj) {
        while(sharedListObj.size() < 1){
          try {
            sharedListObj.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }                    
        }
        // Getting value from the list
        System.out.println("Getting from queue " + Thread.currentThread().getName() + " " + sharedListObj.get(0));
        // To get out of while(true) loop
        if(sharedListObj.get(0) == 5) break;
        sharedListObj.remove(0);
        sharedListObj.notify();                    
      }
    }
  }
}


public class InterThreadDemo {
  public static void main(String[] args) {
    // This is the shared list shared between producer
    // and consumer
    List<Integer> sharedListObj = new ArrayList<Integer>();
    Thread t1 = new Thread(new Producer(sharedListObj), "Producer");
    Thread t2 = new Thread(new Consumer(sharedListObj), "Consumer");
    t1.start();
    t2.start();    
  }
}

Output

Adding to queue - Producer 1
Getting from queue Consumer 1
Adding to queue - Producer 2
Getting from queue Consumer 2
Adding to queue - Producer 3
Getting from queue Consumer 3
Adding to queue - Producer 4
Getting from queue Consumer 4
Adding to queue - Producer 5
Getting from queue Consumer 5

If wait/notify related code is commented though the access is synchronized nothing stops producer thread to keep producing numbers or consumer for keep on consuming numbers. Since I have used a list here and trying to get 0th element from the list it may even lead to ArrayIndexOutofBoundsException.

class Producer implements Runnable{
  List<Integer> sharedListObj;
  Producer(List<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {
    int i = 0;
    while(true){
      synchronized (sharedListObj) {
        // While condition as mandated to avoid spurious wakeup
        /*while(sharedListObj.size() >= 1){
            try {
              sharedListObj.wait();
            } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
        }*/
        // Putting value in the list
        System.out.println("Adding to queue - " + Thread.currentThread().getName() + " " + ++i);
        sharedListObj.add(i);
        //sharedListObj.notify();    
        // To get out of while(true) loop
        if(i > 4) break;
      }
    }
  }            
}

class Consumer implements Runnable{
  List<Integer> sharedListObj;
  Consumer(List<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {    
    while(true){
      synchronized (sharedListObj) {
        /*while(sharedListObj.size() < 1){
          try {
            sharedListObj.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }                    
        }*/
        // Getting value from the list
        System.out.println("Getting from queue " + Thread.currentThread().getName() + " " + sharedListObj.get(0));
        // To get out of while(true) loop
        if(sharedListObj.get(0) == 5) break;
        sharedListObj.remove(0);
        //sharedListObj.notify();        
                
      }
    }
  }
}

public class InterThreadDemo {
  public static void main(String[] args) {
    // This is the shared list shared between producer
    // and consumer
    List<Integer> sharedListObj = new ArrayList<Integer>();
    Thread t1 = new Thread(new Producer(sharedListObj), "Producer");
    Thread t2 = new Thread(new Consumer(sharedListObj), "Consumer");
    t1.start();
    t2.start();    
  }
}

Output

Adding to queue - Producer 1
Adding to queue - Producer 2
Adding to queue - Producer 3
Adding to queue - Producer 4
Exception in thread "Consumer" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
Getting from queue Consumer 1
Getting from queue Consumer 2
Getting from queue Consumer 3
Getting from queue Consumer 4
Adding to queue - Producer 5

 at java.util.ArrayList.rangeCheck(ArrayList.java:653)
 at java.util.ArrayList.get(ArrayList.java:429)
 at org.netjs.examples.Consumer.run(InterThreadDemo.java:55)
 at java.lang.Thread.run(Thread.java:745)

It can be seen, how, in absence of proper inter-thread communication using wait(), notify(), notifyAll() methods, nothing stops producer thread from keep on producing numbers on the other hand when the consumer thread gets hold of the synchronized block code it keeps on consuming numbers.

Refer Print odd-even numbers using threads and wait-notify to see how to print odd-even numbers using wait notify.

That's all for this topic Inter-thread Communication Using wait, notify And notifyAll - Java Multithreading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Race Condition in Java Multi-Threading
  2. Deadlock in Java Multi-Threading
  3. Volatile Keyword in Java With Examples
  4. Java ThreadLocal Class With Examples
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Initializer Block in Java
  2. Constructor Chaining in Java
  3. Varargs (Variable-length Arguments) in Java
  4. Functional Interfaces in Java
  5. Try-With-Resources in Java With Examples
  6. final Vs finally Vs finalize in Java
  7. Garbage Collection in Java
  8. Find All Permutations of a Given String Java Program