Non-blocking method to start several threads and run a callabck on the parent thread when all children have finished

StackOverflow https://stackoverflow.com/questions/19145760

Question

The main thing is that the callback should be on the PARENT thread and not called from the task, which is finishing the job (e.g. NOT like ThreadPoolExecutor's afterExecute() hook). I'd like to have something like:

ExecutorService exec = Executors.newSingleThreadExecutor();
>>>>> exec.addAllJobsFinishedListener(someListener) <<<<<
exec.submit(task);

and someListener to have an Overrideable method like allJobsFinished()

Was it helpful?

Solution

Non-blocking method to start several threads and run a callback on the parent thread when all children have finished

If you want the callback on PARENT thread, then I'm afraid you need to have the parent thread calling exec.awaitTermination(...). After you have submitted all of the jobs and the exec.shutdown() has been called, this waits for the all of the jobs in the thread-pool to complete. If you want this to be non-blocking then you are going to have to do this in another thread (running in a different pool of course).

I don't see how it can be a "listener" running on the parent thread that is also non-blocking. You could have a background thread checking which will update some sort of shared state (like an AtomicBoolean) to be true when the exec.awaitTermination(...) completes.

ThreadPoolExecutor does have terminate() method that you can override. Is that not what you want? Here are the javadocs for the method. Your code would look something like:

ThreadPoolExecutor threadPool =
   new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
      new LinkedBlockingQueue()) {
     public void terminated() {
        super.terminated();
        // do something magic
     }
};
threadPool.execute(task);
// ...
// need to shutdown the pool after you've submitted all of the tasks
threadPool.shutdown();

If the "something magic" code set a shared volatile boolean or an AtomicBoolean that the main thread could check, then it should work fine.

OTHER TIPS

Looks like ThreadPoolExecutor class is really good option for you and you can call getActiveCount() method to check for running threads without being blocked. Also look on this article for example based on shutdown() and isTerminated() which is pretty simple and nice as for me.

What this solution does not cover is waiting cycle. Some kind of sleeping should handle this. Probably standard combination of Condition and Lock (look for POSIX condition variable example) is also acceptable solution for this but it lacks beauty of previous approach.

Look for this, I think it is right for you:

package com.journaldev.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SimpleThreadPool {

    public static void main(String[] args) {

        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread('' + i);
            executor.execute(worker);
        }

        executor.shutdown();

        while (!executor.isTerminated()) {
            // Put other work or calls here...
        }
        System.out.println('Finished all threads');
    }
}

Please pay attention to the following facts:

  • executor.shutdown() just blocks new threads spawning.
  • executor.isTerminated() doesn't block you. You are free to do other job.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top