"notifyAll()" in java threads: unexpected waiting time - java

I am reading some code in OCA/OCP Java SE 7 Programmer I & II Study Guide, and I got stuck on an example:
package threads;
class Totalizer implements Runnable
{
int total = 0;
public void run(){
synchronized(this){
for(int i = 0; i < 100; i++){
total += i;
}
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t){
try {
System.out.println("Waiting for calculation...");
t.wait();
} catch (InterruptedException e) {}
System.out.println(t.total);
}
}
public static void main(String[] args){
Totalizer t = new Totalizer();
new Tester(t).start();
new Tester(t).start();
new Tester(t).start();
}
}
//
When I run main(), it prints:
waiting for calculation...
waiting for calculation...
waiting for calculation...
and nothing happens, no calculation, nothing. I can't figure out what is wrong with this code.

Two points.
The most obvious one is that you never start the Totalizer runnable, so the notifyAll call is never issued. You need to have a line
new Thread(t).start();
somewhere in your main method. But even if you do that, it won't work reliably, as the wait call may be invoked after the notifyAll call. It may also print the output too early, as the wait call can wake up without a notifyAll as well.
The Javadoc for Object.wait() describes what you need to do:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
So, you can't just call Object.wait just like that, if you want to use it correctly. This is because:
You don't know if the condition was already satisfied earlier, before you started waiting
The wait call may also wake up without a notify call
In your case, you need a condition variable that you can check. For example, you can change your code like this:
class Totalizer implements Runnable
{
int total = 0;
boolean calculationComplete; // Condition to check in wait()
public void run() {
for(int i = 0; i < 100; i++) {
total += i;
}
synchronized (this) {
// Indicate condition for wait() is now true
calculationComplete = true;
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t) {
System.out.println("Waiting for calculation...");
// Loop, terminate when condition is true
while (!t.calculationComplete) {
try {
t.wait();
} catch (InterruptedException e) {}
}
System.out.println(t.total);
}
}

Related

Threads notifyAll() [duplicate]

This question already has answers here:
Java: notify() vs. notifyAll() all over again
(26 answers)
Closed 4 years ago.
Given a thread has multiple states: alive runnable running waiting and terminated.
the notifyAll() method is suppose to put all threads that are "waiting" on an object's lock back into the "runnable" state where it is may be chosen as the next running object.
The following example instantiates and starts 3 Reader threads, which go into waiting (wait() method) until the 'calc' object's lock is released. The calc objects thread is instantiated and started just after this where it adds up some numbers, followed by notifyAll().
My question is, why doesn't the calc thread notify all the Reader threads every time? when I run this on my computer it's hit and miss.
public class Reader extends Thread{
Calculator c;
public Reader(Calculator calc){
c=calc;
}
public void run(){
synchronized(c){
try{
System.out.println("Waiting for calculation...");
c.wait();
}catch(InterruptedException e){}
System.out.println("Total is: "+c.total);
}
}
public static void main(String[] args){
Calculator calc = new Calculator();
new Reader(calc).start();
new Reader(calc).start();
new Reader(calc).start();
new Thread(calc).start();
}
}
class Calculator implements Runnable{
int total;
public void run(){
synchronized(this){
for(int i =0; i<100; i++){
total+=i;
}
notifyAll();
}
}
}
When executing multiple threads, order of execution of the threads is not guaranteed.
In your case chances are that the Calculator thread completes it's loop and calls notifyAll() even before any of the Reader threads gets into runnable state. So all Reader will keep waiting and will never print total.
To avoid such situation, in this particular example you can use another flag isCalculated in Calculator and set this flag once computation is done. Reader threads will also check for this flag and wait only when isCalculated is false.
class Reader extends Thread {
Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public void run() {
synchronized (c) {
try {
System.out.println("Waiting for calculation...");
if (!c.isCalculated) { // wait only if calculation is not done
c.wait();
}
} catch (InterruptedException e) {
}
System.out.println("Total is: " + c.total);
}
}
}
class Calculator implements Runnable {
int total;
boolean isCalculated;
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
isCalculated = true; // set flag to mark that computation is complete
notifyAll();
}
}
}
As mentioned by #Sudhir you can check some flags before calling wait ,
check this tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
In your case notifyAll() may be called before wait is called .. so the threads may keep on waiting for the notify to be called

common data in two threads

I want to have two threads. One will increment my variable and the other one will show it on the screen just after it is incremented.
I want to use the wait() and notifyAll() functions to do that but I have some problems.
I have written this code, but it stops working at some point (it shows only the first and the last number: 1 and 10).
public class TestClass {
static int x = 0;
public static Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++) {
synchronized (lock) {
lock.wait();
System.out.println(x);
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; i++) {
synchronized (lock) {
x++;
lock.notifyAll();
}
}
}
});
t2.start();
}
}
I have tried adding additional notifyAll() in the first thread and wait() in the second one(t2) but it still doesn't work. How can I do that right?
From JavaDoc:
The awakened threads will not be able to proceed until the current
thread relinquishes the lock on this object. The awakened threads will
compete in the usual manner with any other threads that might be
actively competing to synchronize on this object; for example, the
awakened threads enjoy no reliable privilege or disadvantage in being
the next thread to lock this object.
The thread that you just woke up is not guaranteed to acquire the lock immediately, thus you could have the loop that calls notifyAll() run all its iterations before the other gets woken up.
If you want them to alternate, one way is to have each one take turns waiting
Below is a working solution. Key is in adding an additional flag that will indicate whether the writing thread has the right to write. Note final on the lock object, that is a good practice.
public class TestClass
{
private static int x = 0;
private static final Object lock = new Object();
private static boolean canWrite = false;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++)
{
synchronized(lock)
{
if(!canWrite)
lock.wait();
System.out.println(x);
canWrite = false;
lock.notify();
}
}
}
catch (InterruptedException e) {}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++)
{
synchronized(lock)
{
x++;
canWrite = true;
lock.notify();
lock.wait();
}
}
} catch (InterruptedException ex) {}
}
});
t1.start();
t2.start();
}
}
The pattern is confusing but if you want to try to control threads, I suppose it's a useful exercise.
Change your code to give your thread a good name e.g. "test1" and "test2", say. Run your program and dig out the process ID for it and run
jstack <pid>
(you can find it in the bin directory of the JDK). This is (perhaps) what you will see:
test1 will be waiting one the
lock.wait();
while test2 will waiting on
lock.wait();
as well.
Start at the first iteration. test2 wins and calls notify, which has no effect at all because nothing is waiting on the lock. test2 then starts waiting.
Now test1 can enter and immediately goes into a wait.
If test1 wins the first time, you can get into a cycle that appears to work.
That is why you get the first number (test2 wins first) or the last number (test1 wins).
That's pretty much what it looks like to me, but your jstack will tell you for sure.
PS: Use CountDownLatch and the concurrency package in general.

Java - While loop with embedded threads bug

I have this code below, that evaluates if three threads are done, and if yes, it continues with the code. The problem is that when I include some sort of print statement before the if statement, it works as usual. However, when I don't include the print, it continues forever. Here it is:
while (!are_we_done) {
System.out.println(are_we_done);
if (thread_arr[0].are_we_done==true && thread_arr[1].are_we_done==true && thread_arr[2].are_we_done==true) {
are_we_done=true;
}
}
Any clue as to what's going on?
Thanks in advance for any help/advice.
The problem was that I had to specify the are_we_done variable in the thread class as volatile.
Your work with threads is awesome - google for 'busy waiting'.
in main thread introduce 'latch = new CountDownLatch(<number of threads>)' variable
pass it into all your threads
on finish of the thread call 'latch.countDown()'
in main thread wait for all spawned threads complete with 'latch.await(...)'
Example:
public static void main(String... args) throws Exception {
Thread[] threads = new Thread[3];
CountDownLatch latch = new CountDownLatch(threads.length);
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new YourRunnable(latch));
threads[i].start();
}
while (!latch.await(1000)) {
System.out.println("Not complete yet");
}
System.out.println("Complete!");
}
public class YourRunndable implements Runnable {
... // fields + constructor
public void run() {
try {
... // do your staff
} finally {
latch.countDown();
}
}
}

Getting a thread to pause - Thread.wait()/Thread.notify()

I'm trying to understand how threads work, and I wrote a simple example where I want to create and start a new thread, the thread, display the numbers from 1 to 1000 in the main thread, resume the secondary thread, and display the numbers from 1 to 1000 in the secondary thread. When I leave out the Thread.wait()/Thread.notify() it behaves as expected, both threads display a few numbers at a time. When I add those functions in, for some reason the main thread's numbers are printed second instead of first. What am I doing wrong?
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
t.start();
synchronized(t) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
You misunderstand how wait/notify works. wait does not block the thread on which it is called; it blocks the current thread until notify is called on the same object (so if you have threads A and B and, while in thread A, called B.wait(), this will stop thread A and not thread B - for as long as B.notify() is not called).
So, in your specific example, if you want main thread to execute first, you need to put wait() inside the secondary thread. Like this:
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
t.start();
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
However, even this code may not work like you want. In a scenario where the main thread gets to the notify() part before the secondary thread had a chance to get to the wait() part (unlikely in your case, but still possible - you can observe it if you put Thread.sleep at the beginning of the secondary thread), the secondary thread will never be waken up. Therefore, the safest method would be something similar to this:
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
synchronized (t) {
t.start();
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
In this example the output is completely deterministic. Here's what happens:
Main thread creates a new t object.
Main thread gets a lock on the t monitor.
Main thread starts the t thread.
(these can happen in any order)
Secondary thread starts, but since main thread still owns the t monitor, the secondary thread cannot proceed and must wait (because its first statement is synchronized (this), not because it happens to be the t object - all the locks, notifies and waits could as well be done on an object completely unrelated to any of the 2 threads with the same result.
Primary thread continues, gets to the t.wait() part and suspends its execution, releasing the t monitor that it synchronized on.
Secondary thread gains ownership of t monitor.
Secondary thread calls t.notify(), waking the main thread. The main thread cannot continue just yet though, since the secondary thread still holds ownership of the t monitor.
Secondary thread calls t.wait(), suspends its execution and releases the t monitor.
Primary thread can finally continue, since the t monitor is now available.
Primary thread gains ownership of the t monitor but releases it right away.
Primary thread does its number counting thing.
Primary thread again gains ownership of the t monitor.
Primary thread calls t.notify(), waking the secondary thread. The secondary thread cannot continue just yet, because the primary thread still holds the t monitor.
Primary thread releases the t monitor and terminates.
Secondary thread gains ownership of the t monitor, but releases it right away.
Secondary thread does its number counting thing and then terminates.
The entire application terminates.
As you can see, even in such a deceptively simple scenario there is a lot going on.
You are lucky that your program terminates at all.
When you call t.wait() your main threads stops and waits indefinitely on a notification.
It never gets it, but I believe is awaken by spurious wakeup when the secondary thread finishes. (Read here on what a spurious wakeup is).
ExampleThread doesn't wait() or notify(), and isn't synchronized on anything. So it will run whenever it can without any coordination with other threads.
The main thread is waiting for a notification which never comes (this notification should be sent by another thread). My guess is that when the ExampleThread dies, the main thread is woken "spuriously," and completes.
The thread that should wait for another to complete must perform the call to wait() inside a loop that checks for a condition:
class ExampleThread extends Thread {
private boolean ready = false;
synchronized void ready() {
ready = true;
notifyAll();
}
#Override
public void run() {
/* Wait to for readiness to be signaled. */
synchronized (this) {
while (!ready)
try {
wait();
} catch(InterruptedException ex) {
ex.printStackTrace();
return; /* Interruption means abort. */
}
}
/* Now do your work. */
...
Then in your main thread:
ExampleThread t = new ExampleThread();
t.start();
/* Do your work. */
...
/* Then signal the other thread. */
t.ready();

A good small example to demonstrate wait() and notify() method in java

Can anybody please provide me a good small example demonstrate wait() and notify() functionality in java. I've tried with the below piece of code but it's not showing what i expected.
public class WaitDemo {
int i = 10;
int display() {
System.out.println("Lexmark");
i++;
return i;
}
}
public class ClassDemo1 extends Thread {
private WaitDemo wd = new WaitDemo();
public static void main(String[] args) {
ClassDemo1 cd1 = new ClassDemo1();
ClassDemo1 cd2 = new ClassDemo1();
cd1.setName("Europe");
cd2.setName("America");
cd1.start();
cd2.start();
}
synchronized void display() {
System.out.println("Hello");
notifyAll();
}
public void run() {
synchronized (this) {
try {
{
notify();
System.out.println("The thread is " + currentThread().getName());
wait();
System.out.println("The value is " + wd.display());
}
} catch (InterruptedException e) {
}
}
}
}
The issue is that the method in the class WaitDemo is not getting executed and as per my idea the SOP after wait() should execute. Please help me out on this.
You've got two levels of braces { in your try block. If you remove the inner set (which doesn't appear to do anything), does that fix the problem?
There are several examples around, all of which demonstrate the use. The last link is a set of results that can help you out. If you need more specific things, let me know what it is that your app is trying to do, and I can try to find examples that are more specific to your situation.
http://www.javamex.com/tutorials/wait_notify_how_to.shtml
http://www.java-samples.com/showtutorial.php?tutorialid=306
http://www.coderanch.com/t/234235/threads/java/Wait-Example
https://www.google.com/search?q=wait%28%29+example+java&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a
Below is an example of wait & notify in the Object class. The customer is trying to withdraw money of value 2000 but the account is having only 1000 so it has to wait for the deposit. Once the deposit is made, then the customer will be able to withdraw the amount. Until the deposit is made, the customer will be waiting.
class Cust {
private int totalAmount = 1000;
public synchronized void withdrawal(int amount) {
System.out.println("Total amount " + totalAmount + " withdrawing amount " + amount);
while (this.totalAmount < amount) {
System.out.println("not enough amount..waiting for deposit..");
try { wait(); } catch (Exception e) {}
}
this.totalAmount -= amount;
System.out.println("Withdrawal successful.. Remaining balance is "+totalAmount);
}
public synchronized void deposit(int amount){
System.out.println("Depositing amount "+amount);
this.totalAmount += amount;
System.out.println("deposit completed...and Now totalAmount is " + this.totalAmount);
notify();
}
}
class Depo implements Runnable {
Cust c; int depo;
Depo(Cust c, int depo){
this.c = c;
this.depo = depo;
}
#Override
public void run() {
c.deposit(depo);
}
}
class Withdrawal implements Runnable {
Cust c; int with;
Withdrawal(Cust c, int with){
this.c = c;
this.with = with;
}
#Override
public void run() {
c.withdrawal(with);
}
}
public class ObjectWaitExample {
public static void main(String[] args) {
Cust c = new Cust();
Thread w = new Thread(new Withdrawal(c, 2000));
Thread d1 = new Thread(new Depo(c, 50));
Thread d2 = new Thread(new Depo(c, 150));
Thread d3 = new Thread(new Depo(c, 900));
w.start();
d1.start();
d2.start();
d3.start();
}
}
I created two threads one for printing odd numbers (OddThread) and another for even numbers (EvenThread). Inside the run method of each of the threads I used the shared object of class Print to call printOdd() and printEven() for the Odd and EvenThread respectively. I made the shared object of Print static so that only one copy is made. Now synchronizing on the Print object I used a Boolean flag such that when the odd thread printed an odd number it will be sent into the waiting state and the at the same time notifying the even thread to execute. The logic is written in such a way that the odd thread will always print the odd number first no matter what, as the flag is set to false initially preventing the even thread to execute and sending it to a waiting state.
package com.amardeep.test;
public class ThreadDemo {
// Shared object
static Print print = new Print();
public static void main(String[] args) {
new Thread(new OddThread()).start();
new Thread(new EvenThread()).start();
}
}
class EvenThread implements Runnable {
#Override
public void run() {
ThreadDemo.print.printEven();
}
}
class OddThread implements Runnable {
#Override
public void run() {
ThreadDemo.print.printOdd();
}
}
class Print {
public volatile boolean flag = false;
public synchronized void printEven() {
for (int i = 1; i <= 10; i++) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if (i % 2 == 0) {
System.out.println("from even " + i);
flag = false;
notifyAll();
}
}
}
}
public synchronized void printOdd() {
for (int i = 1; i <= 10; i++) {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if (i % 2 != 0) {
System.out.println("from odd " + i);
flag = true;
notifyAll();
}
}
}
}
}
output:-
from odd 1
from even 2
from odd 3
from even 4
from odd 5
from even 6
from odd 7
from even 8
from odd 9
from even 10
Your problem is that you are creating two instances of the Thread class. Thus when the wait() is called, it is on two different instances, neither of which has another thread that is in contention for your monitor, nor is there another thread to call notifyAll() to wake the thread from its wait state.
Thus each thread you have started will wait forever (or until interrupted for some other reason).
You want to have multiple threads accessing the same monitor, so start by trying to code something in which the code in question is not actually a thread, but is simply being used by a thread.
#normalocity has already provided links to multiple examples.
I just updated this answer to include an SCCE.
The workers call pauseIfNeeded on the WorkerPauseManager. If the manager is paused when the worker thread calls pauseIfNeeded(), we call wait(), which tells the calling thread to wait until a different thread calls notify() or notifyAll() on the object being waited on. This happens when the Swing Event Dispatch Thread calls play() on the manager, which in turn calls notifyAll().
Note that you must have a synchronized lock on the object you are calling wait() or notify() on. Since the methods in WorkerPauseManager are synchronized, all the synchronized methods are getting a synchronized lock on the WorkerPauseManager itself.
import javax.swing.*;
import java.awt.event.ActionEvent;
/**
* #author sbarnum
*/
public class WorkerPauseManagerTest {
public static void main(String[] args) {
final WorkerPauseManager pauseManager = new WorkerPauseManager();
new Worker("Worker 1", pauseManager).start();
new Worker("Worker 2", pauseManager).start();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") {
public void actionPerformed(final ActionEvent e) {
JToggleButton source = (JToggleButton) e.getSource();
if (source.isSelected()) {
pauseManager.start();
source.setText("Pause");
} else {
pauseManager.pause();
source.setText("Play");
}
}
});
playPauseButton.setSelected(true); // already running
JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE);
System.exit(0);
}
});
}
private static class Worker extends Thread {
final String name;
final WorkerPauseManager pauseManager;
public Worker(final String name, final WorkerPauseManager pauseManager) {
this.name = name;
this.pauseManager = pauseManager;
}
#Override
public void run() {
while (!Thread.interrupted()) {
try {
pauseManager.pauseIfNeeded();
System.out.println(name + " is running");
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public static final class WorkerPauseManager {
private boolean paused;
public synchronized void pauseIfNeeded() throws InterruptedException {
if (paused) wait();
}
public synchronized void pause() {
this.paused = true;
}
public synchronized void start() {
this.paused = false;
notifyAll();
}
}
}
What wait method does is , when some thread executed a synchronized block by locking some object (we call that object is "a") , then inside that synchronized block when the thread executed the wait method of object "a" like this
A a = new A (); // some class object call "a"
synchronized (a){
a.wait ();//exceptions must be handled
}
Then the a object will release and the thread has to go to the wait state until it has been release from that state.
and anothet thread now can use the a object beacause its a release object. so if another thread locked that object and it executed the notify method from that object like
a.notify ()
Then one of a thread of the threads that went to wait state by object "a" can be released from the wait state. Other wise when call the notifyAll then the all the thread objects will release from that state.
/*
* the below program is like
* tread t1 will first run , and it comes to "notify()" method
* there are no threds waiting bcoz this is the first thread.
* so it will not invoke any other threads. next step is "wait()" method
*will be called and the thread t1 in waiting state. next stament
* "System.out.println("The value is ..."+wd.display());" will not be executed
* because thread t1 is in waiting state.
*
* thread t2 will run ,and it comes to "notify()" method ,there is already
* thread t1 is in waiting state ,then it will be invoked.now thread t1 will
* continue execution and it prints the statement "System.out.println("The value is ..."+wd.display())"
* and thread t2 will be in waiting state now.
*
* if you uncomment "notifyAll()" method then, after t1 thread completes its execution
*then immediately "notifyAll()" method will be called,by that time thread t2 is
* already in waiting state , then thread t2 will be invoked and continues execution.
*or
* if any other threadds are in waiting state all those threads will be invoked.
*/
package threadsex;
/**
*
* #author MaheshM
*/
/**
* #param args the command line arguments
*/
public class WaitNotifyNotifyAllDemo implements Runnable {
WaitDemo wd = new WaitDemo();
public static void main(String[] args) {
WaitNotifyNotifyAllDemo cd1 = new WaitNotifyNotifyAllDemo();
Thread t1 = new Thread(cd1);
t1.setName("mahi1");
Thread t2 = new Thread(cd1);
t2.setName("mahi2");
t1.start();
t2.start();
}
#Override
public void run() {
synchronized (this) {
try {
System.out.println("The thread is=" +
Thread.currentThread().getName());
notify();
wait();
System.out.println("The value is ..." + wd.display());
// notifyAll();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}

Categories