views:

118

answers:

8

I have a Java Thread which exposes a property which other threads want to access:

class MyThread extends Thread {
   private Foo foo;
   ...
   Foo getFoo() {
     return foo;
   }
   ...
   public void run() { 
     ...
     foo = makeTheFoo();
     ...
   }
}

The problem is that it takes some short time from the time this runs until foo is available. Callers may call getFoo() before this and get a null. I'd rather they simply block, wait, and get the value once initialization has occurred. (foo is never changed afterwards.) It will be a matter of milliseconds until it's ready, so I'm comfortable with this approach.

Now, I can make this happen with wait() and notifyAll() and there's a 95% chance I'll do it right. But I'm wondering how you all would do it; is there a primitive in java.util.concurrent that would do this, that I've missed?

Or, how would you structure it? Yes, make foo volatile. Yes, synchronize on an internal lock Object and put the check in a while loop until it's not null. Am I missing anything?

A: 

You can use the the wait() and notify() methods:

Simple example here:

http://www.java-samples.com/showtutorial.php?tutorialid=306

David Relihan
Definitely, I can roll a solution by hand. I think it's a tad more complex than this -- the field should be `volatile` and we need `notifyAll()` to start -- so I was hoping for comments on what else I need, or a pre-packaged solution that's definitely right.
Sean Owen
@Sean In that case I would go with DJClayworth's suggestion
David Relihan
A: 

As I understand, concurrent stuff is created explicitly not to wait and do what you want right away — but if it is possible at all. In your case you need to wait until something is available, so your only option is, uh, to wait(). In short, it seems that the way you described it is the only correct way.

doublep
+3  A: 

In general notify() and notifyAll() are the methods you want. notify() is dangerous if only one item is creating the Foo and many threads might wait for it. But I think there are some other issues here.

I wouldn't make the Thread the place to store the Foo. Doing so means you have to keep a thread around after Foo is created. Why not make another object to store the Foo, and have the creating thread write to it?

Then I would have getFoo() test foo and only wait if it was non-null (don't forget to synchronize it with itself and with the foo setter).

DJClayworth
+1 For extracting foo from MyThread
David Relihan
Agree, I wish it weren't so. In this case I really have to make the object within run(). It's a GUI app with weird needs.
Sean Owen
+7  A: 

If foo is initialized only one time, a CountDownLatch is a great fit.

class MyThread extends Thread {

  private final CountDownLatch latch = new CountDownLatch(1);

  ...

  Foo getFoo() throws InterruptedException
  {
    latch.await(); /* Or use overload with timeout parameter. */
    return foo;
  }

  @Override
  public void run() {
    foo = makeTheFoo()
    latch.countDown();
  }

}

Latches provide the same visibility behavior as the volatile keyword, meaning that reading threads will see the value of foo assigned by the thread, even though foo isn't declared volatile.

erickson
you're fast! LOL
Lirik
A: 

If initialization is a one shot deal, try java.util.concurrent.CountDownLatch.

fgantt
A: 

Is lazy initialization an option?

sychronized Foo getFoo() {
    if (foo == null)
        foo = makeFoo();
    }
    return foo;
}
meriton
Not in this case since the foo must be made in the other thread.
Sean Owen
A: 

Try the CountDownLatch:

class MyThread extends Thread {
   private volatile CountDownLatch latch;
   private Foo foo;
   MyThread(){
      latch = new CountDownLatch(1);
   }
   ...
   Foo getFoo() {
     latch.await(); // waits until foo is ready
     return foo;
   }
   ...
   public void run() { 
     ...
     foo = makeTheFoo();
     latch.countDown();// signals that foo is ready
     ...
   }
}

I don't think wait/notifyAll will work, because every wait will expect a notify. You want to notify once and then never bother with notification again, then any other thread that's calling getFoo will either block until foo is initialized or just get foo if it's already initialized.

Lirik
Actually, there's a subtle bug here: since `latch` isn't `final` or `volatile`, it's not guaranteed to be "visible" to other threads. Might not be an issue in practice, but the guarantee doesn't really cost anything.
erickson
+1  A: 

I'd use any of the BlockingQueue's in java.util.concurrent More specifically, if there is one thread waiting for Foo and one producing it I'd use a SynchronousQueue in cases of more producers and/or more consumers my default option is a LinkedBlockingQueue, but other implementations might be better suited to your application. Your code then becomes:

class MyThread extends Thread {
   private SynchronousQueue<Foo> queue = new SynchronousQueue<Foo>();
   ...
   Foo getFoo() {
     Foo foo;
     try {
        foo = queue.take();
     }
     catch (InteruptedException ex) {
        ...stuff ...
     }
     return foo;
   }
   ...
   public void run() { 
     ...
     foo = makeTheFoo();
     try {
        queue.put(foo);
     }
     catch (InteruptedException ex) {
        ...stuff ...
     }
     ...
   }
}
jilles de wit
SynchronousQueue is a handy construct in many cases, but it doesn't fit the requirement here very well: `foo` is only initialized once, and read possibly many times. This would only allow `foo` to be read once. Other attempts to read the property would block forever.
erickson
Yes, you are correct, I had missed the "only initialized once" part. I thought this was more of a producer/consumer situation.
jilles de wit