 <p>You can do all the work in the executing threads of the thread pools using an AtomicInteger to monitor the number of runnables executed</p> <pre><code> int numberOfParties = 5; AtomicInteger numberOfJobsToExecute = new AtomicInteger(1000); ExecutorService pool = Executors.newFixedThreadPool(numberOfParties ); for(int i =0; i &lt; numberOfParties; i++){ pool.submit(new Runnable(){ public void run(){ while(numberOfJobsToExecute.decrementAndGet() &gt;= 0){ makeJobs(1).get(0).run(); } } }); } </code></pre> <p>You can also store the returned Future's in a List and <code>get()</code> on them to await completion (among other mechanisms)</p>