2

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

  1. 如果池中的线程少于 corePoolSize,则为新任务启动一个新线程;
  2. 如果池中有多个 corePoolSize 线程并且所有线程都很忙,则为新任务启动一个新线程,直到达到 maxPoolSize。在这种情况下,拒绝任务;
  3. 保持 corePoolSize 个线程存活,即使它们处于空闲状态,如果它们空闲超过 keepAliveTime,多余的线程将死亡

根据 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,我如何才能知道“活动”线程(空闲或忙碌)的数量?

提前致谢。

4

3 回答 3

1

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

于 2012-01-05T09:18:28.093 回答
1

@arosimakeepAliveTime只对多余的线程生效,而不是核心线程。核心线程将始终保留在池中。我还写了另一个答案来理解,希望对您有所帮助。

于 2017-06-05T11:23:52.913 回答
0

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

于 2012-01-05T08:40:33.690 回答