How to keep core threads alive and die out excess threads in ThreadPoolExecutor? keepAliveTime doesn't work as expected

StackOverflow https://stackoverflow.com/questions/8739591

  •  14-04-2021
  •  | 
  •  

Question

I use ThreadPoolExecutor to manage a thread pool. What we want are:

  1. if the pool has less than corePoolSize threads, kick off a new thread for a new task;
  2. 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;
  3. 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.

Was it helpful?

Solution

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.

OTHER TIPS

@arosima keepAliveTime only takes effect on excess threads rather than core threads. Core threads will be always kept in the pool. I also wrote another answer to understand, hope it helpful.

I am pretty sure the pool size is a target size. I don't think there are any guarantees about shutting down threads (there is no background checker) I think its just a hint. Idle threads give next to no overhead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top