aspose file tools*
The moose likes Threads and Synchronization and the fly likes What's wrong with this code?  (trying wait and notifyall for first time...) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "What Watch "What New topic
Author

What's wrong with this code? (trying wait and notifyall for first time...)

M Marsden
Greenhorn

Joined: Jun 18, 2008
Posts: 18
Okay, the following was my attempt to do the programming project on threads on page 233 of the 2005 ed. of Heller and Roberts Complete Java 2 Certification. (I know the answer's on the CD, but I got the book from the library and the CD was missing.) The basic point of the question was to have one Rendezvous and several Waiters (specified by command-line) all going to the hurry up and wait and get notified and come back at different times. (So you could see how the threads would return in different orders, presumably.) My program never gets past the first Waiter, for some reason. Little help? (Thanks!

class Rendezvous {
static int i;
synchronized void hurryUpAndWait() {
i++;
try {
wait();
} catch (InterruptedException ex) { }
}
}

class Waiter extends Thread {
int waiterid;
Rendezvous rendewait = new Rendezvous();
Waiter(Rendezvous rende) {
waiterid += 1;
rende=rendewait;
run();
}
public void run() {
System.out.println("starting run for " +waiterid);
rendewait.hurryUpAndWait();
System.out.println("Notification has happened for Waiter ID #"+waiterid);
}
}
public class NotifyLab {


public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
Rendezvous rennot = new Rendezvous();
Waiter[] newwaiter = new Waiter[x];
while (x > 0) {
newwaiter[x] = new Waiter(rennot);
newwaiter[x].start();
System.out.println(x +"newwaiter was started.");
x--;
}

rennot.notifyAll();
}

}
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Well, without going into every detail, I see two or three major things wrong here. First, I see that nothing calls "notify" until every thread has been started; perhaps that's intentional. I really can't tell what the logic is supposed to be.

But... wait() and notify() operate with respect to individual objects, and generally, the idea is that multiple things are competing to wait on one single object. But you're creating a zillion Rendezvous objects, even though clearly the whole point of the exercise is for all the threads to share a single one, communicating through it.

Also in the Waiter constructor, you set the constructor parameter equal to the already-initialized member, when perhaps you mean to do just the opposite.


[Jess in Action][AskingGoodQuestions]
Norm Radder
Ranch Hand

Joined: Aug 10, 2005
Posts: 687
    
    1
<blockquote>code:
<pre name="code" class="java">
int x = Integer.parseInt(args[0]);
Rendezvous rennot = new Rendezvous();
Waiter[] newwaiter = new Waiter[x];
while (x > 0) {
newwaiter[x] = new Waiter(rennot);
</pre>
</blockquote>

Seems like this code should get:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
The size of the array (x) is used as the value of its index. BOOM!
[ July 11, 2008: Message edited by: Norm Radder ]
M Marsden
Greenhorn

Joined: Jun 18, 2008
Posts: 18
Okay, thanks for the feedback -- I've cleaned the code up some and it's almost working, I feel, (it's building several threads at least now), but when it hits the notifyAll, I get "current thread not owner"... any idea why? Here's the latest version:


[HENRY: Added Code Tags]
[ July 13, 2008: Message edited by: Henry Wong ]
Norm Radder
Ranch Hand

Joined: Aug 10, 2005
Posts: 687
    
    1
One thing wrong with your program is you don't explain with comments in the code why each Waiter creates a new Rendezvous(); in the run method. You create one in the main() method also.

I recommend another pass thru your textbook to see how synchronized and monitors work and how to use wait() and notifyAll(). They only work if they are used in the same object. If there are lots of new object floating around, its not going to work.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40

but when it hits the notifyAll, I get "current thread not owner"... any idea why?


There are actually quite a few things wrong with your application... but to answer your question...



To call the notifyAll() method, of the object referred to by the rennot variable, you need to own the lock of that object. Synchronizing on the newwaiter reference only works, if both references happen to refer to the same object.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
M Marsden
Greenhorn

Joined: Jun 18, 2008
Posts: 18
Thanks for the feedback everyone - I still haven't quite got this, but I feel like I'm getting closer - I think I'm down to one Rendezvous instance, for example (which is how it should be...) The problem with the following code is that the run() method can't see the rennot argument -- how do I pass the Rendezvous from the constructor to the run method?

class Rendezvous {
static int i;
synchronized void hurryUpAndWait() {
i++;
try {
wait();
} catch (InterruptedException ex) { }
}
}

class Waiter extends Thread {
static int waiteridpool;
int waiterid = waiteridpool;
Waiter(Rendezvous rennot) {
waiteridpool += 1;
start();
}

public void run() {
System.out.println("starting run for " +waiterid);
// Can't seem to access rennot from within the run method
// There's a 'cannot find symbol' error on the next line
rennot.hurryUpAndWait();
System.out.println("Notification has happened for Waiter ID #"+waiterid);
}
}
public class NotifyLab {
public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
Rendezvous rennot = new Rendezvous();
Waiter[] newwaiter = new Waiter[x];
while (x > 0) {
newwaiter[x-1] = new Waiter(rennot);
System.out.println(x +"newwaiter was started.");
x--;
}
}

}
Norm Radder
Ranch Hand

Joined: Aug 10, 2005
Posts: 687
    
    1
basic point of the question was to have one Rendezvous and several Waiters ... all going to the hurry up and wait and get notified and come back at different times.

What does this mean? How does the program show success?

For a method (run) in the Waiter class to see the value of an arg(rennot) to the Constructor, the Constructor needs to save it(rennot) in a class variable.

I don't see the notifyAll() to get any waiting threads started again.
[ July 13, 2008: Message edited by: Norm Radder ]
M Marsden
Greenhorn

Joined: Jun 18, 2008
Posts: 18
Well, the point of the program is to get several threads running and see what order they come back in when notifyAll runs. I've finally got a version of the program running that seems to do that - thanks to everyone who commented. I'm not 100% sure this program is operating correctly though, since there's supposed to be one Rendezvous instance, and I feel like I've got two at least (since I've got two 'new' Rendevous), but they may end up referring to the same Object - it seems like the one in NotifyLab is a dummy object that just gets the Waiter constructor to run to me, and probably could be eliminated...

class Rendezvous {
static int i;
synchronized void hurryUpAndWait() {
i++;
try {
wait();
} catch (InterruptedException ex) { }
}
}

class Waiter extends Thread {
static int waiteridpool;
int waiterid = waiteridpool;
static Rendezvous rennotW = new Rendezvous();
Waiter(Rendezvous rennotN) {
rennotN=rennotW;
waiteridpool += 1;
start();
}

public void run() {
System.out.println("starting run for " +waiterid);
rennotW.hurryUpAndWait();
System.out.println("Notification has happened for Waiter ID #"+waiterid);
}
}
public class NotifyLab {
Rendezvous rennot;
public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
Rendezvous rennot = new Rendezvous();
Waiter[] newwaiter = new Waiter[x];
while (x > 0) {
newwaiter[x-1] = new Waiter(rennot);
System.out.println(x +"newwaiter was started.");
x--;
}
synchronized(Waiter.rennotW) {
Waiter.rennotW.notifyAll();
System.out.println("Just notifyAll-ed");
}
}
}
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: What's wrong with this code? (trying wait and notifyall for first time...)