Discussion:
How to notify specific thread??
(too old to reply)
bunallo
2005-02-25 02:44:37 UTC
Permalink
If I have x number of threads that is waiting and I only want to notify a
specific thread how do I do this?

The situation is that I have some threads that needs to wait until a
specific object is inserted into a Database (made as a hashtable). When that
object is inserted into the database only the thread that waited for this
specific object is supposed to be notified.

I have made a notifyAll () call and then a while loop that checks if there
is one of all the newly notified that inserted the object. Each time this
while loop is false the wait is invoked on the thread.

But I would like to be able to notify only the correct thread. Heard this
could be done by making each thread lock on a unique object, but I can't
seem to make any sense out of it.

Hope someone can give me some ideas!
k***@comcast.net
2005-02-25 02:51:08 UTC
Permalink
I don't think there is anyway you can. The only way to make sure that
the thread you want is notified is by calling notifyAll().
Chris Smith
2005-02-25 02:52:27 UTC
Permalink
Post by bunallo
If I have x number of threads that is waiting and I only want to notify a
specific thread how do I do this?
The situation is that I have some threads that needs to wait until a
specific object is inserted into a Database (made as a hashtable). When that
object is inserted into the database only the thread that waited for this
specific object is supposed to be notified.
I have made a notifyAll () call and then a while loop that checks if there
is one of all the newly notified that inserted the object. Each time this
while loop is false the wait is invoked on the thread.
But I would like to be able to notify only the correct thread. Heard this
could be done by making each thread lock on a unique object, but I can't
seem to make any sense out of it.
It is impossible to notify a specific thread that's waiting on a
monitor. All you can do is notify all of them, or notify one of them
(chosen by no particular criteria). You've already discovered that you
need to notify all of them.

The "while" loop you mentioned is called a predicate loop, is IT IS
ALWAYS REQUIRED TO CORRECTLY USE WAIT for any purpose. Got that? It's
not a symptom of bad design, and it's not something to be avoided or
worked around. It has to be there. It is just plain impossible to
write correct code to call Object.wait() without it.

If you need to optimize this code to avoid a "thundering herd" kind of
performance issue, then you can split the monitor into several monitors.
There's a whole range of ways you can do this; in fact, a complete
continuum between using one monitor, as one extreme, or using a monitor
per object, as the other. In between, you can create any constant
number of monitors, and categorize the objects between them somehow
(perhaps based on a digest of Object.hashCode() for instance). You need
to provide more information if you want a more complete answer.
--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
bunallo
2005-02-25 12:56:51 UTC
Permalink
Post by Chris Smith
If you need to optimize this code to avoid a "thundering herd" kind of
performance issue, then you can split the monitor into several monitors.
There's a whole range of ways you can do this; in fact, a complete
continuum between using one monitor, as one extreme, or using a monitor
per object, as the other. In between, you can create any constant
number of monitors, and categorize the objects between them somehow
(perhaps based on a digest of Object.hashCode() for instance). You need
to provide more information if you want a more complete answer.
Ok I have tried something else:

Each time I create a thread it gets added to a vector v. In the run method
of this thread I have a flag. If this flag for some reason is set to true
then that current thread will be set to wait:

run(){

if (flag_wait){
synchronized(this){
try{
flag_wait = false;
wait();
}
catch(InterruptedException e){}
}
}
}

If I create two threads and sets their flag_wait to true, I will now in my
vector v have two threads that are waiting at index 0 and index 1.


Now I create a third thread that should only notify thread a index 1.
Therefore I would like to have another type of thread that has a reference
to this vector and this in its run method:

run(){

if (flag_notify){
synchronized(this){
try{

flag_notify = false;
v.get(1).notifyAll(); // now only thread at index 1 should
be notified!
}
catch(InterruptedException e){}
}
}
}


But for some reason I cannot run notifyAll() on a thread in a vector!

Hope its possible to understand
Tilman Bohn
2005-02-25 13:41:57 UTC
Permalink
In message <cvn70f$q09$***@news.net.uni-c.dk>,
bunallo wrote on Fri, 25 Feb 2005 13:56:51 +0100:

[...]
Post by bunallo
Each time I create a thread it gets added to a vector v. In the run method
of this thread I have a flag. If this flag for some reason is set to true
run(){
if (flag_wait){
synchronized(this){
You now synchronize on this Runnable. Without knowing your code it is
impossible to tell if that is the same object you end up putting in your
Vector, but let's assume it is (for now).
Post by bunallo
try{
flag_wait = false;
wait();
Now the executing thread is added to the wait set associated with this
Runnable instance, and the lock is relinquished.
Post by bunallo
}
catch(InterruptedException e){}
}
}
}
You have already been told in no uncertain terms to _only_ _ever_
call wait() in a while loop. Please heed this advice. If you don't
believe it, don't start to argue but read the many many past threads
discussing this point first!
Post by bunallo
If I create two threads and sets their flag_wait to true, I will now in my
vector v have two threads that are waiting at index 0 and index 1.
Now I create a third thread that should only notify thread a index 1.
Therefore I would like to have another type of thread that has a reference
run(){
if (flag_notify){
For all I know, flag_notify could be false all the time so this block
might never run. How should anyone know?
Post by bunallo
synchronized(this){
Now you synchronize on _this_ Runnable. That's certainly another
object than the one the wait() in the other thread is synchronizing on.
Post by bunallo
try{
flag_notify = false;
v.get(1).notifyAll(); // now only thread at index 1 should
be notified!
So at this point you are synchronized on the lock associated with this
Runnable instance, but very probably (impossible to say for sure without
seeing the rest of the code, but very probably) not on the one the
wait() above is using as a monitor. Therefore you will likely see an
IllegalMonitorStateException here.
Post by bunallo
}
catch(InterruptedException e){}
}
}
}
But for some reason I cannot run notifyAll() on a thread in a vector!
Did you get a CannotRunNotifyAllOnThreadInVectorException, or what
makes you say that?
--
Cheers, Tilman

`Boy, life takes a long time to live...' -- Steven Wright
Chris Smith
2005-02-25 14:18:32 UTC
Permalink
Post by bunallo
Each time I create a thread it gets added to a vector v. In the run method
of this thread I have a flag. If this flag for some reason is set to true
On what? You need a specific monitor to wait on. That monitor needs to
be shared with other threads, which intend to call notify() on it. I'm
not generally as picky about this as some other members of the group...
but you've shown yourself not very adept at supplying the information we
need in code snippets and error messages to answer your questions on the
newsgroup. If you want help, the best thing for you to do is post
complete example code in the future, so that we can compile and run in
ourselves.

One more comment...
Post by bunallo
if (flag_wait){
synchronized(this){
try{
flag_wait = false;
wait();
}
catch(InterruptedException e){}
}
This lacks a predicate loop, and so it's hopelessly broken. You need to
change the "if" statement to a "while" statement, and the notifying
thread needs to clear flag_wait, *not* the waiting thread. The entire
predicate loop should be inside the synchronized block.

I'd also recommend that you forget all about optimizing until you've got
something working. Use *one* shared object as a monitor, and not a
Vector or anything else. Once that's working, you can try something
else.
--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Paul van Rossem
2005-02-25 16:06:48 UTC
Permalink
Post by bunallo
If I have x number of threads that is waiting and I only want to notify a
specific thread how do I do this?
The situation is that I have some threads that needs to wait until a
specific object is inserted into a Database (made as a hashtable). When that
object is inserted into the database only the thread that waited for this
specific object is supposed to be notified.
I have made a notifyAll () call and then a while loop that checks if there
is one of all the newly notified that inserted the object. Each time this
while loop is false the wait is invoked on the thread.
But I would like to be able to notify only the correct thread. Heard this
could be done by making each thread lock on a unique object, but I can't
seem to make any sense out of it.
Hope someone can give me some ideas!
Use a java.util.concurrent.Semaphore (only available in 1.5).

Paul.
Tony Dahlman
2005-02-26 03:33:35 UTC
Permalink
Post by Paul van Rossem
Post by bunallo
If I have x number of threads that is waiting and I only want to notify a
specific thread how do I do this?
The situation is that I have some threads that needs to wait until a
specific object is inserted into a Database (made as a hashtable). When that
object is inserted into the database only the thread that waited for this
specific object is supposed to be notified.
I have made a notifyAll () call and then a while loop that checks if there
is one of all the newly notified that inserted the object. Each time this
while loop is false the wait is invoked on the thread.
But I would like to be able to notify only the correct thread. Heard this
could be done by making each thread lock on a unique object, but I can't
seem to make any sense out of it.
Hope someone can give me some ideas!
Use a java.util.concurrent.Semaphore (only available in 1.5).
Paul.
Ooh, what a package!

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/package-summary.html

BlockingQueue, a decoupling CompletionService, a ScheduledExecutorService, and
a ThreadFactory class.

Not to mention Semaphore, which maybe doesn't help the
OP. ;-( Can he/she really awaken just one of maybe a hundred wait()ing threads
without awakening them all? I assume we don't know in advance in what order the
threads need to be awakened.

But never mind, because this package of classes and methods is, yes I think the
word is, "rad!" If it all works as described in the API, Sun and Java may take
the entire market for ATM code and servers.

Normally, I try to stay two or three releases behind "the latest", to be sure
that any code I write will run anywhere, but a read through this package's API
makes me want to download 1.5 and start playing with the newest Java library.
(I may still wait a year or two, however.)

Thanks for the tip, Paul!

-- Tony Dahlman
Tilman Bohn
2005-02-26 08:35:02 UTC
Permalink
In message <***@jps.net>,
Tony Dahlman wrote on Sat, 26 Feb 2005 03:33:35 GMT:

[...]
Post by Tony Dahlman
Normally, I try to stay two or three releases behind "the latest", to be sure
that any code I write will run anywhere, but a read through this package's API
makes me want to download 1.5 and start playing with the newest Java library.
(I may still wait a year or two, however.)
No need to wait for 1.5. This is really an improved version of Doug
Lea's util.concurrent package, which you can also get for 1.4 under at
least two different guises. The original one (which actually works under
1.2+) at Oswego:

http://makeashorterlink.com/?X13F222E ,

or if you prefer to be able to easily switch to the official API later,
Dawid Kurzyniec's backport of this to 1.4:

http://www.mathcs.emory.edu/dcl/util/backport-util-concurrent/
--
Cheers, Tilman

`Boy, life takes a long time to live...' -- Steven Wright
Loading...