This week's book giveaway is in the Programmer Certification forum.
We're giving away four copies of OCP Oracle Certified Professional Java SE 21 Developer Study Guide: Exam 1Z0-830 and have Jeanne Boyarsky & Scott Selikoff on-line!
See this thread for details.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

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

 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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();
}

}
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Rancher
Posts: 5035
38
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
<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
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Rancher
Posts: 5035
38
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
M Marsden
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Rancher
Posts: 5035
38
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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");
}
}
}
 
Opportunity is missed by most people because it is dressed in overalls and looks like work - Edison. Tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic