WaitForMultipleObject feature in Java

Discussion in 'Java' started by yancheng.cheok@gmail.com, Jun 12, 2007.

  1. Guest

    Current, I have a method, which will perform lock on

    void MyWait()
    {
    CountDownLatch.aWait
    // We can have access to the Stop lock.
    }

    void MyStop()
    {
    // Signal Stop lock.
    }

    This works fine until we need to stop the thread from keep waiting on
    CountDownLatch, when there is a stop signal. (The method who send stop
    signal doesn't have access to CountDownLatch, else, the stop method
    can just directly signal the CountDownLatch)

    We would like to have something, "if either CountDownLatch is signaled
    or Stop lock is signaled", unblock the thread.

    Perhaps something like

    WaitForMultipleObject(CountDownLatch, StopLock) in method void
    MyWait()

    either one of the object being signaled, the thread will continue
    execution.

    May I know how can I do that in Java?

    One of the solution is that I can interrupt the Thread which is halted
    at line CountDownLatch.aWait. However, I have no access to the Thread
    which halted at line CountDownLatch.aWait
    , Jun 12, 2007
    #1
    1. Advertising

  2. Twisted Guest

    On Jun 11, 11:44 pm, wrote:
    > WaitForMultipleObject(CountDownLatch, StopLock) in method void
    > MyWait()
    >
    > either one of the object being signaled, the thread will continue
    > execution.


    I don't think there's a pre-existing feature in Java to do this. But
    it is simple: use two threads, as follows. Say you want to do
    aFoo.quackQuack() when either the lock on object locker1 or the lock
    on object locker2 is released, whichever comes first.

    Code elsewhere:

    Thread code:

    private Object lock;
    private Foo theFoo;
    private boolean hasQuackQuackedTheFoo;
    private Set<QuackerThread> threadSet;

    public QuackerThread (Object lock, Foo theFoo) {
    this.lock = lock;
    this.theFoo = theFoo;
    hasQuackQuackedTheFoo = false;
    threadSet = new HashSet<QuackerThread>();
    threadSet.add(this);
    }

    public QuackerThread (Object lock, QuackerThread anotherThread) {
    this.lock = lock;
    this.theFoo = anotherThread.theFoo;
    hasQuackQuackedTheFoo = false;
    threadSet = anotherThread.threadSet;
    threadSet.add(this);
    }

    public boolean hasTheFooBeenQuackQuacked () {
    return hasQuackQuackedTheFoo;
    }

    public void run () {
    lock.wait();
    quackQuackTheFooIfNecessary();
    doWhateverElse();
    }

    public void quackQuackTheFooIfNecessary () {
    synchronized (threadSet) {
    for (QuackerThread t : threadSet) if
    (t.hasTheFooBeenQuackQuacked()) return;
    theFoo.quackQuack();
    hasQuackQuackedTheFoo = true;
    }
    }


    and elsewhere ...

    QuackerThread t1 = new QuackerThread (locker1, aFoo);
    QuackerThread t2 = new QuackerThread (locker2, t1);
    (new Thread(t1)).start();
    (new Thread(t2)).start();

    t1 will be created with lock == locker1, theFoo == aFoo, and threadSet
    a set containing just t1.
    t2 will be created with lock == locker2, theFoo == aFoo (because
    t1.theFoo == aFoo), and threadSet the same set containing just t1, and
    add itself to that set, so that t1 and t2 both reference the same
    Set<QuackerThread> containing just t1 and t2.

    As soon as one of locker1 or locker2 is notified, t1 or t2
    (respectively) will wake up and enter the critical section locked by
    threadSet's monitor. It will find out if either of the threads has
    already quackQuacked aFoo, and if neither has, it will quackQuack it
    and put up its own quackQuacked flag. When the second of the lock
    objects is notified, the other thread will enter the critical section.
    It will have to wait for the first one to leave, and will then find on
    polling that that thread has quackQuacked aFoo already, and simply
    return.

    So, aFoo gets quackQuacked exactly once, as soon as either of the two
    locks is released, without getting quackQuacked a second time when the
    second lock is released. doWhateverElse on the other hand is run once
    for each thread when its respective lock has been notified.

    This can be extended to three or more locks:

    QuackerThread t3 = new QuackerThread(locker3, t1) or
    QuackerThread t3 = new QuackerThread(locker3, t2) followed by
    (new Thread(t3)).start()

    should lead to a single quackQuacking whenever the first of the three
    objects is notified, and so forth; the constructor that takes a
    preexisting QuackerThread adds the new thread to whichever pool
    contains the existing thread with the property that as soon as any of
    the lock objects passed to any of their constructors is notified, the
    quackQuack occurs, and only the once due to that pool. The other
    constructor makes a QuackerThread in a pool by itself, to use as a
    starting point for building a larger pool, or to quackQuack when a
    single specific object gets notified, whichever.

    This lets you quackQuack on a "logical OR" of object notifications. If
    quackQuack does "someThing.notify()" this lets you cause the
    notification of any of a set of objects notify "someThing", but only
    the once.

    public class NotifyOr extends Foo {
    private Object thingToNotify;
    public NotifyOr (Object thingToNotify, Set<Object> things) {
    this.thingToNotify = thingToNotify;
    QuackerThread t = null;
    for (Object o : things) {
    if (t == null)
    t = new QuackerThread(o, this);
    else
    t = new QuackerThread(o, t);
    (new Thread(t)).start();
    }
    }
    public void quackQuack () {
    thingToNotify.notify();
    }
    }

    It's comparatively very easy to build a "NotifyAnd":

    public class NotifyAnd implements Runnable {
    private Object thingToNotify;
    private Set<Object> things;
    public NotifyAnd (Object thingToNotify, Set<Object> things) {
    this.thingToNotify = thingToNotify;
    this.things = things;
    (new Thread(this)).run();
    }
    public void run () {
    for (Object o : things) o.wait();
    thingToNotify.notify();
    }
    }
    Twisted, Jun 12, 2007
    #2
    1. Advertising

  3. Guest

    On Jun 12, 12:36 pm, Twisted <> wrote:
    > On Jun 11, 11:44 pm, wrote:
    >
    > > WaitForMultipleObject(CountDownLatch, StopLock) in method void
    > > MyWait()

    >
    > > either one of the object being signaled, the thread will continue
    > > execution.

    >
    > I don't think there's a pre-existing feature in Java to do this. But
    > it is simple: use two threads, as follows. Say you want to do
    > aFoo.quackQuack() when either the lock on object locker1 or the lock
    > on object locker2 is released, whichever comes first.
    >
    > Code elsewhere:
    >
    > Thread code:
    >
    > private Object lock;
    > private Foo theFoo;
    > private boolean hasQuackQuackedTheFoo;
    > private Set<QuackerThread> threadSet;
    >
    > public QuackerThread (Object lock, Foo theFoo) {
    > this.lock = lock;
    > this.theFoo = theFoo;
    > hasQuackQuackedTheFoo = false;
    > threadSet = new HashSet<QuackerThread>();
    > threadSet.add(this);
    >
    > }
    >
    > public QuackerThread (Object lock, QuackerThread anotherThread) {
    > this.lock = lock;
    > this.theFoo = anotherThread.theFoo;
    > hasQuackQuackedTheFoo = false;
    > threadSet = anotherThread.threadSet;
    > threadSet.add(this);
    >
    > }
    >
    > public boolean hasTheFooBeenQuackQuacked () {
    > return hasQuackQuackedTheFoo;
    >
    > }
    >
    > public void run () {
    > lock.wait();
    > quackQuackTheFooIfNecessary();
    > doWhateverElse();
    >
    > }
    >
    > public void quackQuackTheFooIfNecessary () {
    > synchronized (threadSet) {
    > for (QuackerThread t : threadSet) if
    > (t.hasTheFooBeenQuackQuacked()) return;
    > theFoo.quackQuack();
    > hasQuackQuackedTheFoo = true;
    > }
    >
    > }
    >
    > and elsewhere ...
    >
    > QuackerThread t1 = new QuackerThread (locker1, aFoo);
    > QuackerThread t2 = new QuackerThread (locker2, t1);
    > (new Thread(t1)).start();
    > (new Thread(t2)).start();
    >
    > t1 will be created with lock == locker1, theFoo == aFoo, and threadSet
    > a set containing just t1.
    > t2 will be created with lock == locker2, theFoo == aFoo (because
    > t1.theFoo == aFoo), and threadSet the same set containing just t1, and
    > add itself to that set, so that t1 and t2 both reference the same
    > Set<QuackerThread> containing just t1 and t2.
    >
    > As soon as one of locker1 or locker2 is notified, t1 or t2
    > (respectively) will wake up and enter the critical section locked by
    > threadSet's monitor. It will find out if either of the threads has
    > already quackQuacked aFoo, and if neither has, it will quackQuack it
    > and put up its own quackQuacked flag. When the second of the lock
    > objects is notified, the other thread will enter the critical section.
    > It will have to wait for the first one to leave, and will then find on
    > polling that that thread has quackQuacked aFoo already, and simply
    > return.
    >
    > So, aFoo gets quackQuacked exactly once, as soon as either of the two
    > locks is released, without getting quackQuacked a second time when the
    > second lock is released. doWhateverElse on the other hand is run once
    > for each thread when its respective lock has been notified.
    >
    > This can be extended to three or more locks:
    >
    > QuackerThread t3 = new QuackerThread(locker3, t1) or
    > QuackerThread t3 = new QuackerThread(locker3, t2) followed by
    > (new Thread(t3)).start()
    >
    > should lead to a single quackQuacking whenever the first of the three
    > objects is notified, and so forth; the constructor that takes a
    > preexisting QuackerThread adds the new thread to whichever pool
    > contains the existing thread with the property that as soon as any of
    > the lock objects passed to any of their constructors is notified, the
    > quackQuack occurs, and only the once due to that pool. The other
    > constructor makes a QuackerThread in a pool by itself, to use as a
    > starting point for building a larger pool, or to quackQuack when a
    > single specific object gets notified, whichever.
    >
    > This lets you quackQuack on a "logical OR" of object notifications. If
    > quackQuack does "someThing.notify()" this lets you cause the
    > notification of any of a set of objects notify "someThing", but only
    > the once.
    >
    > public class NotifyOr extends Foo {
    > private Object thingToNotify;
    > public NotifyOr (Object thingToNotify, Set<Object> things) {
    > this.thingToNotify = thingToNotify;
    > QuackerThread t = null;
    > for (Object o : things) {
    > if (t == null)
    > t = new QuackerThread(o, this);
    > else
    > t = new QuackerThread(o, t);
    > (new Thread(t)).start();
    > }}
    >
    > public void quackQuack () {
    > thingToNotify.notify();
    >
    > }
    > }
    >
    > It's comparatively very easy to build a "NotifyAnd":
    >
    > public class NotifyAnd implements Runnable {
    > private Object thingToNotify;
    > private Set<Object> things;
    > public NotifyAnd (Object thingToNotify, Set<Object> things) {
    > this.thingToNotify = thingToNotify;
    > this.things = things;
    > (new Thread(this)).run();}
    >
    > public void run () {
    > for (Object o : things) o.wait();
    > thingToNotify.notify();
    >
    > }
    > }


    It look very complicated. I think I need to take sometime to digest,
    test it out and get back to you.
    , Jun 13, 2007
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. KS
    Replies:
    5
    Views:
    9,347
    David Zimmerman
    Nov 9, 2003
  2. christopher diggins

    Java Feature Proposal

    christopher diggins, Feb 4, 2004, in forum: Java
    Replies:
    18
    Views:
    574
    Adam Jenkins
    Feb 10, 2004
  3. winwin

    Feature of Sun Java 2

    winwin, Apr 14, 2004, in forum: Java
    Replies:
    4
    Views:
    395
    Roedy Green
    Apr 19, 2004
  4. Replies:
    9
    Views:
    466
    Timo Stamm
    Jun 2, 2006
  5. Banibrata Dutta
    Replies:
    0
    Views:
    216
    Banibrata Dutta
    Apr 28, 2008
Loading...

Share This Page