The spec for ThreadPoolExecutor requires poolSize to not drop below
corePoolSize due to timeouts.
But:
import java.util.*;
import java.util.concurrent.*;
public class TimeOutShrink {
    static void print(ThreadPoolExecutor pool) {
	System.out.printf("poolSize=%d core=%d max=%d%n",
			  pool.getPoolSize(),
			  pool.getCorePoolSize(),
			  pool.getMaximumPoolSize());
    }
    public static void main(String[] args) throws Throwable {
	final int n = 4;
	final CyclicBarrier barrier = new CyclicBarrier(2*n+1);
	final ThreadPoolExecutor pool
	    = new ThreadPoolExecutor(n, 2*n, 5L, TimeUnit.SECONDS,
				     new SynchronousQueue<Runnable>());
	final Runnable r = new Runnable() { public void run() {
	    try {
		barrier.await();
		barrier.await();
	    } catch (Throwable t) { t.printStackTrace(); }}};
	for (int i = 0; i < 2*n; i++)
	    pool.execute(r);
	barrier.await();
	print(pool);
	barrier.await();
	Thread.sleep(10*1000);
	print(pool);
	pool.shutdown();
	pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
    }
}
prints:
poolSize=8 core=4 max=8
poolSize=0 core=4 max=8
but should print
poolSize=8 core=4 max=8
poolSize=4 core=4 max=8