Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)?

like image 757
Paul Reiners Avatar asked Nov 30 '22 10:11

Paul Reiners


2 Answers

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.

like image 112
Dirk Avatar answered Dec 04 '22 11:12

Dirk


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();
like image 43
Marcus Adams Avatar answered Dec 04 '22 10:12

Marcus Adams