I use an ExecutorService to execute a task. This task can recursively create other tasks which are submitted to the same ExecutorService and those
You could use a runner that keeps track of running threads:
Runner runner = Runner.runner(numberOfThreads);
runner.runIn(2, SECONDS, callable);
runner.run(callable);
// blocks until all tasks are finished (or failed)
runner.waitTillDone();
// and reuse it
runner.runRunnableIn(500, MILLISECONDS, runnable);
runner.waitTillDone();
// and then just kill it
runner.shutdownAndAwaitTermination();
to use it you just add a dependency:
compile 'com.github.matejtymes:javafixes:1.3.0'