wait() and notify() Simple example

🔄 Understanding wait() and notify() in Java (with Example)

In multithreaded programming, thread coordination is often needed when multiple threads work on the same shared resource.
In Java, this coordination is achieved using the wait() and notify() methods from the Object class.


⚙️ What Are wait() and notify()?

🕒 wait()

  • Causes the current thread to pause its execution and release the lock on the object it’s holding.

  • The thread stays in the waiting state until another thread calls notify() or notifyAll() on the same object.

  • Must be called inside a synchronized block.

🚀 notify()

  • Wakes up one thread that is waiting on the same object’s monitor.

  • The awakened thread will compete to reacquire the lock and continue execution.

💡 Important:
Both wait() and notify() must be used inside synchronized blocks or methods, otherwise a java.lang.IllegalMonitorStateException will be thrown.


🧩 Example — Coordinating Two Threads Using wait() and notify()

In the below example:

  • Two threads share the same ArrayList resource.

  • removeRecord thread waits until there’s data to remove.

  • addRecord thread adds a record and then notifies the waiting thread to continue.


💻 Java Code

package com.vinod.test; import java.util.ArrayList; import java.util.List; /** * Demonstrates wait() and notify() for thread communication. * * In this example: * - One thread adds a student record. * - Another thread waits until the record is added, then removes it. * * @author vinod */ public class ConcurrentTest { public static void main(String[] args) { final List<String> students = new ArrayList<>(); // Thread 1: Adds a record after some delay Thread addRecord = new Thread(() -> { System.out.println("AddRecord thread started..."); try { Thread.sleep(10000); // simulate delay before adding } catch (InterruptedException e) { e.printStackTrace(); } synchronized (students) { System.out.println("Thread 1 locked the list and adding student details..."); students.add("Pretech"); System.out.println("Student details added by Thread 1: " + students); // Notify waiting thread students.notify(); System.out.println("Thread 1 sent notification to waiting thread."); } }); // Thread 2: Waits until a record is available to remove Thread removeRecord = new Thread(() -> { System.out.println("RemoveRecord thread started..."); synchronized (students) { System.out.println("Thread 2 locked the list..."); if (students.isEmpty()) { try { System.out.println("List is empty — Thread 2 waiting for notification..."); students.wait(); // releases lock and waits } catch (InterruptedException e) { e.printStackTrace(); } } // Remove record after being notified if (!students.isEmpty()) { System.out.println("Removing item: " + students.get(0)); students.remove(0); } System.out.println("Student list after removal by Thread 2: " + students); } }); addRecord.start(); removeRecord.start(); } }

🧾 Example Output

RemoveRecord thread started... Thread 2 locked the list... List is emptyThread 2 waiting for notification... AddRecord thread started... Thread 1 locked the list and adding student details... Student details added by Thread 1: [Pretech] Thread 1 sent notification to waiting thread. Removing item: Pretech Student list after removal by Thread 2: []

🧠 Step-by-Step Explanation

Step 1: removeRecord thread starts first and locks the students list. Step 2: It finds the list empty → calls wait() → releases the lock → waits. Step 3: addRecord thread starts, acquires the lock, and adds a student. Step 4: After adding, it calls notify() → signals the waiting thread. Step 5: removeRecord thread wakes up, reacquires the lock, removes the record. Step 6: Both threads complete their tasks safely without race conditions.

🧩 Text-Based Visualization

Thread 2: wait() ─────────┐ │ Thread 1: add + notify() ─┘ wakes Thread 2

At any given time:

  • Only one thread holds the lock on the shared resource (students).

  • The wait() call temporarily releases that lock.

  • The notify() call signals another waiting thread to resume once the lock becomes available.


🧱 Key Points to Remember

MethodDescription
wait()Pauses the current thread and releases the lock
notify()Wakes up one waiting thread on the same object
notifyAll()Wakes up all threads waiting on the same object
Must use inside synchronizedRequired for thread safety and correct monitor behavior
Common use caseProducer–Consumer and resource coordination patterns

⚠️ Common Mistakes to Avoid

  1. ❌ Calling wait() or notify() outside a synchronized block → throws IllegalMonitorStateException.

  2. ❌ Forgetting to handle InterruptedException.

  3. ❌ Not checking condition again after wait() (always recheck the condition in a loop in real applications).

  4. ❌ Using shared resource without proper synchronization → causes data inconsistency.


✅ Best Practice

In real-world scenarios, always use a while loop around wait() to handle spurious wake-ups:

while (students.isEmpty()) { students.wait(); }

This ensures that the thread only proceeds when the condition is actually met.


Difference between HashSet ,LinkedHashSet and TreeSet

Difference between HashSet ,LinkedHashSet and TreeSet?

1. HashSet not maintaining any order ,LInkedHashSet maintaining the insertion Order ,TreeSet is maintaining the Sorting order

2. HashSet and LinkedHashSet uses equals() method in Java for comparison but TreeSet uses compareTo() method

3. HashSet and LinkedHashSet allows null values but TreeSet doesn't allow null values

Example

Here is one example to show the difference between HashSet ,LinkedHashSet and TreeSet

 

package com.vinod.test;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class HashExample {
    public static void main(String[] args) {
        Set<String> hs = new HashSet<String>();
        hs.add("vinod");
        hs.add("santhosh");
        hs.add("ajay");

        Set<String> ts = new TreeSet<String>();
        ts.add("vinod");
        ts.add("santhosh");
        ts.add("ajay");

        Set<String> ls = new LinkedHashSet<String>();
        ls.add("vinod");
        ls.add("santhosh");
        ls.add("ajay");

        System.out.println("Hashset " + hs); // No order
        System.out.println("TreeSet " + ts);// Natural ordering
        System.out.println("LinkedHashSet " + ls); // Insertion order

    }

}

Output

Hashset [vinod, santhosh, ajay]

TreeSet [ajay, santhosh, vinod]

LinkedHashSet [vinod, santhosh, ajay]

Done!!! 

 

What is the purpose of serialVersionUID

What is serialVersionUID ?

The serialVersionUID is an identifier for serialized objects. If the serialVersionUID of a serialized object doesn't match to the current serialVersionUID of that class, then the deserialization throws an InvalidClassException.

Here is one example, we have a customer class which is having the default serilVersionUID

package com.vinod.test;

import java.io.Serializable;

public class Customer implements Serializable{

    /**
     *
     */

    private static final long serialVersionUID = 1L;
    private String name;
    private String address;
   
    public Customer(String name, String address) {
        super();
        this.name = name;
        this.address = address;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Customer [name=" + name + ", address=" + address + "]";
    }
   
}
 

Let us serialize this object

package com.vinod.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializeTest {
    public static void main(String[] args) {
        // Serialization
        Customer customer = new Customer("vinod", "bangalore");
        System.out.println("Serialization started.");
        FileOutputStream fos;
        try {
            fos = new FileOutputStream("customer.ser");
            ObjectOutputStream oos;
            oos = new ObjectOutputStream(fos);
            oos.writeObject(customer);
            oos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }
        System.out.println("Serialization completed.");

    }

}
 

Now change the serialVersionUID in the customer class and try to Deseralize

    private static final long serialVersionUID = 2L;

package com.vinod.test;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializeTest {

    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("customer.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Customer deserializedObj;
            deserializedObj = (Customer) ois.readObject();
            System.out.println("DeSerialized SerializableObject: " + deserializedObj);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}
 

Output

java.io.InvalidClassException: com.vinod.test.Customer; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

To avoid this casting exception we have to keep the same serialVersionUID  for serializable objects and de-serialization will be successfull. If we are not adding this version uid  JVM will generate add the default id for each objects and it is possible to do the serialization and de-serialization but after the serialization is there any changes happened in the serializable class then it will throw the Invalid cast exception during de-serialization (Objects wont match)
eg: If i am adding below phone number details to Customer class after the serialization and it will throw the invalid cast exception while de-serialization (if we have same serialVersionUID over there in the class it wont throw exception) 

Done!!--

 

JQuery Hello world example

JQuery

jQuery is a lightweight JavaScript library which make it easier to user JavaScript in web pages

Please see more detail About Jquery .

We can download jQuery library from http://jquery.com/download/ and add the source details inside script tag

Example

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title> 
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.1.1.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function(){
$("#jqueryMessage").html("Hello world ..this is from JQuery");
});
</script>
<div id="jqueryMessage">
</div>
</body>
</html>

Output





image

How to create Deadlocks using Java thread

DeadLock

Deadlock describes a situation where two or more threads are blocked forever, waiting for each other
Here is one simple example to create dead lock and remove deadlock using Java threads

package com.vinod.test;

import java.util.ArrayList;
import java.util.List;

/**
 * In this program two threads are trying to read students and teachers details.
 *
 *@authorvinod
 *
 */
public class SimpleDeadLock {
public static void main(String[] args) {
final List<String> students = new ArrayList<String>();
students.add("Raju");
students.add("Radha");

final List<String> teachers = new ArrayList<String>();
teachers.add("Gopal");
teachers.add("Ragav");

Thread t1 = new Thread() {
public void run() {
synchronized (students) {
System.out.println("Now thread 1 locked student arraylist");
System.out.println("students details from thread1" + students);

try {
Thread.sleep(110);
} catch (InterruptedException e) {
}

synchronized (teachers) {
System.out.println("Now thread 1 locked teacher arraylist");
System.out.println("teacher details from thread1" + teachers);
}
}
}
};

Thread t2 = new Thread() {
public void run() {
synchronized (teachers) {
System.out.println("Now thread 2 locked teacher arraylist");
System.out.println("teacher details from thread 2" + teachers);
try {
Thread.sleep(110);
} catch (InterruptedException e) {
}

synchronized (students) {
System.out.println("Now thread 2 locked student arraylist");
System.out.println("students details from thread2" + students);
}
}
}
};

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

 

Output

Now thread 2 locked teacher arraylist
Now thread 1 locked student arraylist
students details from thread1[Raju, Radha]
teacher details from thread 2[Gopal, Ragav]

How to remove this deadlock?

This above example will never end and each thread is waiting for the resources mutually. Here i am changing the order of synchronization block and remove the dead lock

package com.vinod.test;

import java.util.ArrayList;
import java.util.List;

/**
 * In this program two threads are trying to read students and teachers details.
 *
 *@authorvinod
 *
 */
public class SimpleDeadLock {
public static void main(String[] args) {

final List<String> students = new ArrayList<String>();
students.add("Raju");
students.add("Radha");

final List<String> teachers = new ArrayList<String>();
teachers.add("Gopal");
teachers.add("Ragav");

Thread t1 = new Thread() {
public void run() {
synchronized (students) {
System.out.println("Now thread 1 locked student arraylist");
System.out.println("students details from thread1" + students);

try {
Thread.sleep(110);
} catch (InterruptedException e) {
}

synchronized (teachers) {
System.out.println("Now thread 1 locked teacher arraylist");
System.out.println("teacher details from thread1" + teachers);
}
}
}
};

Thread t2 = new Thread() {
public void run() {
synchronized (students) {
System.out.println("Now thread 2 locked student arraylist");
System.out.println("students details from thread2" + students);
}
synchronized (teachers) {
System.out.println("Now thread 2 locked teacher arraylist");
System.out.println("teacher details from thread 2" + teachers);
try {
Thread.sleep(110);
} catch (InterruptedException e) {
}

}
}
};

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

Output

Now thread 1 locked student arraylist
students details from thread1[Raju, Radha]
Now thread 1 locked teacher arraylist
teacher details from thread1[Gopal, Ragav]
Now thread 2 locked student arraylist
students details from thread2[Raju, Radha]
Now thread 2 locked teacher arraylist
teacher details from thread 2[Gopal, Ragav]

How to create Readonly Collections

Read Only Collections


Following methods available in Collections class to make the collections as read only.

The Collections class has six methods to help out here:
1. unmodifiableCollection(Collection c)
2. unmodifiableList(List list)
3. unmodifiableMap(Map m)
4. unmodifiableSet(Set s)
5. unmodifiableSortedMap(SortedMap m)
6. unmodifiableSortedSet(SortedSet s)
If you get an Iterator from one of these unmodifiable collections, when you call remove(), it will throw an UnsupportedOperationException.

Example

package com.search;

import java.util.*;

public class ReadOnlyCollections {
    public static void main(String[] args) {
        List ar = new ArrayList();
        ar.add("Vinod");
        ar.add("Raj");
        ar.add("Raghav");
        ar.add("Santhosh");
        System.out.println("Before removal " + ar);
        ar = Collections.unmodifiableList(ar);
        Iterator<String> it = ar.iterator();
        while (it.hasNext()) {
            String name = it.next().toString();
            if (name.equals("Raj")) {
                it.remove();
            }
        }
        System.out.println("After removal " + ar);
    }

}

Output
Before removal [Vinod, Raj, Raghav, Santhosh] Exception in thread "main" java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection$1.remove(Unknown Source) at com.search.ReadOnlyCollections.main(ReadOnlyCollections.java:18)

 

JSF Data table Simple example

JSF 2 DataTable

In JSF we can create data table to iterate collection or array or values and display or edit in to JSF pages. Here is one simple example to display data table using h:dataTable tag.
Steps
  • Create a Managed bean which contains the collection of records which needs to be displayed in JSF page
  • Create a JSF page and create h:dataTable component


1. Create a Customer class

package com.vinod.jsf;

public class Customer {
    private String name;
    private String address;
    private String phonenumber;
    public String getPhonenumber() {
        return phonenumber;
    }
    public void setPhonenumber(String phonenumber) {
        this.phonenumber = phonenumber;
    }
    public Customer(String name, String address, String phoneNumber) {
        super();
        this.name = name;
        this.address = address;
        this.phonenumber = phoneNumber;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}
2. Create a Managed Bean
package com.vinod.jsf;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class DataTableBean {

    public DataTableBean() {
    }
    public List getCustomers() {
        List customers = new ArrayList();
        customers.add(new Customer("vinod", "Bangalore", "7777777777"));
        customers.add(new Customer("hari", "chennai", "7777447777"));
        customers.add(new Customer("Jithesh", "Pala", "7777557777"));
        return customers;

    }
}
3. Create a jsf Page
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>My JSF Examples</title>
</head>
<h:body>
    <h:form id="vinod">
        <h:dataTable value="#{dataTableBean.customers}" var="customer">
            <h:column>
                <f:facet name="header">Name</f:facet>
                    #{customer.name}
                      </h:column>
            <h:column>
                <f:facet name="header">Address</f:facet>
                    #{customer.address}
                </h:column>
            <h:column>
                <f:facet name="header">Phone Number</f:facet>
                    #{customer.phonenumber}
                </h:column>
        </h:dataTable>
    </h:form>
</h:body>
</html>
4. Run Application

https://github.com/kkvinodkumaran/myrepository/tree/master/vinod-jsf
Done..download application ..use mvn jetty:run to run the application

Model Context Protocol (MCP) — Complete Guide for Backend Engineers

  Model Context Protocol (MCP) — Complete Guide for Backend Engineers Build Tools, Resources, and AI-Driven Services Using LangChain Moder...

Featured Posts