views:

156

answers:

6
+4  Q: 

Waiting on threads

I have a method that contains the following (Java) code:

doSomeThings();
doSomeOtherThings();

doSomeThings() creates some threads, each of which will run for only a finite amount of time. The problem is that I don't want doSomeOtherThings() to be called until all the threads launched by doSomeThings() are finished. (Also doSomeThings() will call methods that may launch new threads and so on. I don't want to execute doSomeOtherThings() until all these threads have finished.)

This is because doSomeThings(), among other things will set myObject to null, while doSomeOtherThings() calls myObject.myMethod() and I do not want myObject to be null at that time.

Is there some standard way of doing this kind of thing (in Java)?

+5  A: 

Take a look at Thread.join() method.

I'm not clear on your exact implementation but it seems like doSomeThings() should wait on the child threads before returning.

Inside of doSomeThings() method, wait on the threads by calling Thread.join() method.

When you create a thread and call that thread's join() method, the calling thread waits until that thread object dies.

Example:

// Create an instance of my custom thread class
MyThread myThread = new MyThread();
// Tell the custom thread object to run
myThread.start();
// Wait for the custom thread object to finish
myThread.join();
Marcus Adams
-1 Invoking myThread.run will not start up a new thread. The fact that myThread.join() is being called when myThread.run() is finished is only because of the program order and not for any asynchronus reason
John V.
Should have been `myThread.start()` in that example.
Donal Fellows
@Donal, Oops. Thanks. I updated the answer. @John, sorry, it was a typo. I'm used to inheriting from Runnable instead of Thread.
Marcus Adams
+9  A: 

You may want to have a look at the java.util.concurrent package. In particular, you might consider using the CountDownLatch as in

package de.grimm.game.ui;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

public static void main(String[] args) 
throws Exception {

    final ExecutorService executor = Executors.newFixedThreadPool(5);
    final CountDownLatch latch = new CountDownLatch(3);

    for( int k = 0; k < 3; ++k ) {

        executor.submit(new Runnable() {
            public void run() {
                // ... lengthy computation...
                latch.countDown();
            }
        });
    }

    latch.await();

    // ... reached only after all threads spawned have
    // finished and acknowledged so by counting down the
    // latch.

    System.out.println("Done");
}
}

Obviously, this technique will only work, if you know the number of forked threads beforehand, since you need to initialize the latch with that number.

Another way would be to use condition variables, for example:

boolean done = false;

void functionRunInThreadA() {

    synchronized( commonLock ) {

        while( !done ) commonLock.wait();
    }

    // Here it is safe to set the variable to null
}

void functionRunInThreadB() {

    // Do something...

    synchronized( commonLock ) {
        done = true;
        commonLock.notifyAll();
    }
}

You might need to add exception handling (InteruptedException) and some such.

Dirk
(+1) `CountdownLatch` is extremely handy
skaffman
+3  A: 

You are looking is the executorservice and use the futures :)

See http://java.sun.com/docs/books/tutorial/essential/concurrency/exinter.html

So basically collect the futures for all the runnables that you submit to the executor service. Loop all the futures and call the get() methods. These will return when the corresponding runnable is done.

momania
A: 

Another option is to sleep your main thread, and have it check every so often if the other threads have finished. However, I like Dirk's and Marcus Adams' answers better - just throwing this out here for completeness sake.

aperkins
+1  A: 

Another useful more robust Synchronization Barrier you can use that would do the similar functionality as a CountdownLatch is a CyclicBarrier. It works similar to a CountdownLatch where you have to know how many parties (threads) are being used, but it allows you to reuse the barrier as apposed to creating a new instance of a CountdownLatch every time.

I do like momania's suggestion of using an ExecutorService, collecting the futures and invoking get on all of them until they complete.

John V.
A: 

Depends on what exactly you are trying to do here. Is your main concern the ability to dynamically determine the various threads that get spawned by the successive methods that get called from within doSomeThings() and then be able to wait till they finish before calling doSomeOtherThings() ? Or it is possible to know the threads that are spawned at compile time ? In the later case there are number of solutions but all basically involve calling the Thread.join() method on all these threads from wherever they are created.

If it is indeed the former , then you are better off using ThreadGroup and its enumerate() method. This gives you a array of all threads spawned by doSomeThings() if you have properly added new threads to the ThreadGroup. Then you can loop through all thread references in the returned array and call join() on the main thread just before you call doSomeOtherThings() .

Bhaskar