wait and notify methods to synchronize access to this object.
package com.mtitek.threads;
class MyClass {
private volatile boolean ready = false;
private Integer[] elements;
public synchronized boolean isReady() {
return ready;
}
public synchronized void setReady(boolean ready) {
this.ready = ready;
}
public synchronized Integer[] getElements() {
return elements;
}
public synchronized void setElements(Integer[] elements) {
this.elements = elements;
}
}
public class MainClass {
public static void main(String[] args) {
final MyClass myClass = new MyClass();
Runnable myRunnable1 = new Runnable() {
@Override
public void run() {
synchronized (myClass) {
try {
// Wait while another thread might be using the object
while (myClass.isReady()) {
myClass.wait();
}
// Code to be executed by the thread
System.out.println(
Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ")");
System.out.println("Initializing array elements (start)");
myClass.setElements(new Integer[] { 4, 2, 8, 1, 6 });
System.out.println("Initializing array elements (end)");
// Mark as ready and notify waiting threads
myClass.setReady(true);
myClass.notify();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupted status
System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
}
}
}
};
Runnable myRunnable2 = new Runnable() {
@Override
public void run() {
synchronized (myClass) {
try {
// Wait until data is ready
while (!myClass.isReady()) {
myClass.wait();
}
// Process the data
System.out.println(
Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ")");
System.out.println("Sorting and displaying array elements (start)");
Integer[] elements = myClass.getElements();
if (elements != null) {
// Sort the array
java.util.Arrays.sort(elements);
for (Integer element : elements) {
System.out.println(element);
}
}
System.out.println("Sorting and displaying array elements (end)");
// Reset state and notify
myClass.setReady(false);
myClass.notify();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupted status
System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
}
}
}
};
Thread myThread1 = new Thread(myRunnable1, "myFirstThread");
Thread myThread2 = new Thread(myRunnable2, "mySecondThread");
myThread1.start();
myThread2.start();
// Wait for threads to complete
try {
myThread1.join();
myThread2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("Main thread was interrupted: " + e.getMessage());
}
}
}
Output:myFirstThread (19) Initializing array elements (start) Initializing array elements (end) mySecondThread (20) Sorting and displaying array elements (start) 1 2 4 6 8 Sorting and displaying array elements (end)
notifyAll method is used to wake up all threads that are currently waiting on the same object's monitor.
Unlike notify, which wakes only one waiting thread (chosen arbitrarily by the JVM), notifyAll ensures that all waiting threads become eligible for scheduling and will compete for the monitor lock.
package com.mtitek.threads;
public class MainClass {
public static void main(String[] args) {
final Object lock = new Object();
Runnable myRunnable = new Runnable() {
@Override
public void run() {
synchronized (lock) {
try {
System.out.println(Thread.currentThread().getName() + " is waiting.");
lock.wait();
System.out.println(Thread.currentThread().getName() + " has been notified and resumed.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupted status
System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
}
}
}
};
// Create and start two threads that will wait on the same lock
Thread myThread1 = new Thread(myRunnable, "myFirstThread");
Thread myThread2 = new Thread(myRunnable, "mySecondThread");
myThread1.start();
myThread2.start();
// Pause to ensure all threads are waiting
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("Main thread was interrupted: " + e.getMessage());
return;
}
// Notifier thread
Thread notifierThread = new Thread(() -> {
synchronized (lock) {
System.out.println("NotifierThread is calling notifyAll.");
lock.notifyAll(); // Wake up all waiting threads
}
}, "NotifierThread");
notifierThread.start();
// Wait for all threads to complete
try {
myThread1.join();
myThread2.join();
notifierThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("Main thread was interrupted: " + e.getMessage());
}
}
}
Output:myFirstThread is waiting. mySecondThread is waiting. NotifierThread is calling notifyAll. myFirstThread has been notified and resumed. mySecondThread has been notified and resumed.