CompletionService<PartialSolution> comp = new ExecutorCompletionService<>(executor); // Submit initial runners comp.submit(new PartialSolutionTask()); ... long current = System.currentTimeMillis(); // Only wait 30 total seconds final long end = current + TimeUnit.SECONDS.toMillis(30); while (current < end) { Future<PartialSolution> f = comp.poll(end - current, TimeUnit.MILLISECONDS); if (f == null) { // Timeout break; } // Submit a new task using the results of the previous task comp.submit(new PartialSolutionTask(f.get())); current = System.currentTimeMillis(); } // Still should have the same number of running tasks so wait for them to finish by calling comp.poll() N times