# Monitors in Java

In 
Published 2022-12-03

This tutorial explains the usage of Monitors in Java.

For instance, we can think of a table. We have some producers which put products on the table and consumers which takes the products from the table. The consumer takes the product(s) from the table only when the producer(s) notify that one or more products are on the table.

In my example, I start from a simple Spring Boot application created using Spring initializr.

Let's take a look at the following example.

I will create 2 thread. One for simulating a consumer and one for simulating a producer. Here are the classes:

MyThreadProducer.class
package com.exampe.java;

public class MyThreadProducer extends Thread {

    Integer threadNumber;
    
    // object's monitor
    final String table;

    public MyThreadProducer(Integer threadNumber, String table) {
        this.threadNumber = threadNumber;
        this.table = table;
    }

    public void run()
    {
        System.out.println("Thread " + this.threadNumber + " is running...");

        for (int i = 1; i <= 5; i++) {
            try {
                System.out.println("/Thread " + this.threadNumber + "/ wants to put the products on the table.");
                synchronized (table) {
                    System.out.println("/Thread " + this.threadNumber + "/ PUT the products on the table.");
                    Thread.sleep(1000);
                    // You notify that the products could be taken.
                    table.notify();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized (table) {
            table.notify();
        }
        System.out.println("Thread " + this.threadNumber + " stopped.");
    }
}
MyThreadConsumer.class
package com.exampe.java;

public class MyThreadConsumer extends Thread {

    Integer threadNumber;
    final String table;

    public MyThreadConsumer(Integer threadNumber, String table) {
        this.threadNumber = threadNumber;
        this.table = table;
    }

    public void run()
    {
        System.out.println("Thread " + this.threadNumber + " is running...");
        System.out.println(table.hashCode());
        for (int i = 1; i <= 5; i++) {
            try {
                System.out.println("/Thread " + this.threadNumber + "/ is waiting for taking the products.");
                synchronized (table) {
                    // You are waiting for the notification which allow you to take the products
                    table.wait();
                    System.out.println("/Thread " + this.threadNumber + "/ TOOK the products from the table.");
                    Thread.sleep(1000);
                }

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
        System.out.println("Thread " + this.threadNumber + " stopped.");
    }
}

Here is my main class :

package com.exampe.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) throws InterruptedException {

    SpringApplication.run(DemoApplication.class, args);

    System.out.println("--------------------------------------------");

    String table1 = "Table1";

    MyThreadProducer t1 = new MyThreadProducer(1, table1);
    MyThreadConsumer t2 = new MyThreadConsumer(2, table1);

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

    // Waiting for the threads to complete
    t1.join(); t2.join();
    System.out.println("--------------------------------------------");
    System.out.println("End of the execution");
  }
}

When I run the code I get (the result is different for each run):

--------------------------------------------
Thread 1 is running...
/Thread 1/ wants to put the products on the table.
/Thread 1/ PUT the products on the table.
Thread 2 is running...
-1797510589
/Thread 2/ is waiting for taking the products.
/Thread 1/ wants to put the products on the table.
/Thread 1/ PUT the products on the table.
/Thread 1/ wants to put the products on the table.
/Thread 2/ TOOK the products from the table.
/Thread 2/ is waiting for taking the products.
/Thread 1/ PUT the products on the table.
/Thread 1/ wants to put the products on the table.
/Thread 1/ PUT the products on the table.
/Thread 1/ wants to put the products on the table.
/Thread 2/ TOOK the products from the table.
/Thread 2/ is waiting for taking the products.
/Thread 1/ PUT the products on the table.
/Thread 2/ TOOK the products from the table.
Thread 1 stopped.
/Thread 2/ is waiting for taking the products.