I use ThreadPoolExecutor to manage a thread pool. What we want are:
- if the pool has less than corePoolSize threads, kick off a new thread for a new task;
- if the pool has more than corePoolSize threads and all are busy, kick off a new thread for a new task until maxPoolSize is reached. In that case, reject the task;
- keep corePoolSize number of threads alive even if they are idling, excess threads will die if they have been idle for more than keepAliveTime
According the Java6 docs, keepAliveTime should work as above. But in my test code, it doesn’t work consistently.
When I set keepAliveTime to 0, it works fine, always keeping core threads alive and terminating excess threads when they finish;
but, as shown below, when I set keepAliveTime to a positive value, it seems that it terminate ALL idle threads, no matter they are core threads or not.
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 500, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
assertFalse("Not allow core threads to time out.", executor.allowsCoreThreadTimeOut());
Task task_1 = new Task(1000);
Task task_2 = new Task(1000);
Task task_3 = new Task(1000);
executor.execute(task_1);
executor.execute(task_2);
executor.execute(task_3);
Thread.sleep(1050L);
assertEquals("Completed 3 tasks.", 3, executor.getCompletedTaskCount());
assertEquals("Three threads are in the pool.", 3, executor.getPoolSize());
Thread.sleep(600L);
//////// This assertion will fail: **expected <2> but was <0>**
assertEquals("Two threads are in the pool.", 2, executor.getPoolSize());
////----
private static class Task implements Runnable {
private long sleepMillis;
public Task(final long sleepMillis) {
this.sleepMillis = sleepMillis;
}
public void run() {
try { Thread.sleep(sleepMillis);
} catch (Exception e) { System.out.println(e); }
}
}
Is there any misunderstanding about keepAliveTime or getPoolSize? If getPoolSize is not the correct API, how can I get to know the number of “alive” threads (idle or busy)?
Thanks in advance.
Java 7 passes the test. Apparently java 6 has a bug. Reading its code, all threads can exit when the queue is empty, that is definitely wrong for core threads.