如何在ThreadPoolExecutor中保持核心线程活着并消除多余的线程? keepAliveTime无法按预期工作

时间:2012-01-05 08:31:03

标签: java threadpool executor

我使用ThreadPoolExecutor来管理线程池。我们想要的是:

  1. 如果池的corePoolSize线程少于corePoolSize线程,则为新任务启动新线程;
  2. 如果池中有多个corePoolSize线程且所有线程都忙,则启动新线程以执行新任务,直到达到maxPoolSize。在这种情况下,拒绝任务;
  3. 保持corePoolSize线程的数量,即使它们是空闲的,多余的线程如果空闲时间超过keepAliveTime
  4. 根据Java6文档,keepAliveTime应该如上所述。但是在我的测试代码中,它并不一致。

    当我将keepAliveTime设置为0时,它工作正常,始终保持核心线程处于活动状态并在完成时终止多余的线程;
    但是,如下所示,当我将keepAliveTime设置为正值时,它似乎终止所有空闲线程,无论它们是否是核心线程。

    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); }
        }
    }
    

    对keepAliveTime或getPoolSize有什么误解吗?如果getPoolSize不是正确的API,我如何才能知道“活动”线程的数量(空闲或忙碌)?

    提前致谢。

3 个答案:

答案 0 :(得分:1)

Java 7通过了测试。显然java 6有一个bug。读取代码时,所有线程都可以在队列为空时退出,这对于核心线程来说肯定是错误的。

答案 1 :(得分:1)

@arosima keepAliveTime仅对多余的线程而不是核心线程生效。核心线程将始终保留在池中。我还写了another answer来理解,希望它有用。

答案 2 :(得分:0)

我很确定池大小是目标大小。我不认为有任何关于关闭线程的保证(没有背景检查器)我认为它只是一个提示。空闲线程几乎没有开销。