views:

340

answers:

6

I have a thread and I need to wait for its result, like this:

t1.start();
while (variableModifiedByMyThread == null) {
    /* do nothing */
}
// "t1" set the value of "variableModifiedByMyThread"

The code above is working, but not a very nice solution...

Is this code doing the same thing (is it waiting for the "t1" thread)?

t1.start();
try {
    t1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
// "t1" thread finished
+1  A: 

What your second code does is watch t1, and wait for it to die. Once t1 dies, it will start up again. See the javadoc for that method.

aperkins
+1  A: 

Yes, except you're not wasting CPU cycles by checking the variable every chance you get. This is a much better way to do it.

This is assuming the variable is only modified when t1 is finished. If t1 is supposed to modify the variable and stay alive, this will not work.

Incidentally, you should never simply spin in a loop like that to wait. You should at the very least call Thread.yield() inside the loop; otherwise you are potentially looping many times before allowing any other thread to run.

Edit: Actually, come to think of it, a one-element BlockingQueue is probably what you really want. This sounds like a producer-consumer problem (especially if you're doing it more than once), and BlockingQueue is built for just that sort of thing.

Michael Myers
+3  A: 

The former is waiting for a variable to be set, the latter is waiting for the thread to die. If the variable is set just before the thread dies there is little difference except:

  • The former "spins" - the waiting thread is doing something (checking the variable) all the time - very wasteful!
  • The latter can be interrupted by another thread.
Draemon
Your answer is much clearer than mine is. +1 :)
aperkins
A: 
public class Test{
  private final Object lock = new Object();
  private Object var = null;

  public void starThreadAndWaitForOutput(){
    Thread t1 = new Thread(new Runnable(){
      public void run(){
        synchronized(lock){
          var=new Object();
          lock.notify();
        }
      }
    }).start();

    synchronized(lock){
      while(var==null)
        lock.wait();
    }

    System.out.println("We have the var and thread 1 is still going!");
  }
}
Charlie
This is not quite right, you should protect against spurious wake-ups.(See the java.lang.Object.wait javadoc for info about this).The upshot is you should say: synchronized (lock) { while (var == null) { lock.wait(); } }
daveb
You're right! I made the suggested fix.
Charlie
+3  A: 

Consider Futures. The idea is that you have some computation that will be completed "some time in the future" and you can then check if it has completed, or wait for it.

From the javadoc:

 FutureTask<String> future =
   new FutureTask<String>(new Callable<String>() {
     public String call() {
       return searcher.search(target);
   }});
 executor.execute(future);
Adam Batkin
Upvote, but with the added note that you don't even have to wrap it in a FutureTask.. Just submit it to an ExecutorService
Tim
A: 

You could use t1.yield() to pause the thread as long as you the condition holds true.

vinaynag