 <p>There is a workaround to this problem. Consider the following implementation:</p> <pre><code>int corePoolSize = 40; int maximumPoolSize = 40; ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue&lt;Runnable&gt;()); threadPoolExecutor.allowCoreThreadTimeOut(true); </code></pre> <p>By setting the <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html#allowCoreThreadTimeOut%28boolean%29" rel="nofollow">allowCoreThreadTimeOut()</a> to <code>true</code>, the threads in the pool are allowed to terminate after the specified timeout (60 seconds in this example). With this solution, it is the <code>corePoolSize</code> constructor argument that determines the maximum pool size in practice, because the thread pool will grow up to the <code>corePoolSize</code>, and then start adding jobs to the queue. It is likely that the pool may never grow bigger than that, because the pool will not spawn new threads until the queue is full (which, given that the <code>LinkedBlockingQueue</code> has an <code>Integer.MAX_VALUE</code> capacity may never happen). Consequently, there is little point in setting <code>maximumPoolSize</code> to a larger value than <code>corePoolSize</code>.</p> <p>Consideration: The thread pool have 0 idle threads after the timeout has expired, which means that there will be some latency before the threads are created (normally, you would always have <code>corePoolSize</code> threads available).</p> <p>More details can be found in the JavaDoc of <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html" rel="nofollow">ThreadPoolExecutor</a>.</p>