java - 如何在 ThreadPoolExecutor 中保持核心线程存活并淘汰多余线程? keepAliveTime 没有按预期工作

标签 java threadpool executor

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

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

根据 Java6 文档,keepAliveTime 应该像上面那样工作。但在我的测试代码中,它并不能始终如一地工作。

当我将 keepAliveTime 设置为 0 时,它工作正常,始终保持核心线程处于 Activity 状态并在它们完成时终止多余的线程;
但是,如下所示,当我将 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,我如何才能知道“Activity ”线程(空闲或繁忙)的数量?

提前致谢。

最佳答案

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

关于java - 如何在 ThreadPoolExecutor 中保持核心线程存活并淘汰多余线程? keepAliveTime 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8739591/

相关文章:

c++ - pthread退出时运行函数

java - 我必须在应用程序退出时手动关闭 Executor 吗?

java - 将 Java 套接字从线程 A 传递到 B

java - Proguard 剩余部分

java - 几个 JDK TimeZone 函数的 joda-time 等价物是什么

c# - 如何在 .NET 3.5 中重用线程

Java 计划执行器 : Does it guarantee to not run in parallel if task hast not yet finished

java - 如何使用java中的spark以word格式查看LDA主题建模中的主题

java - 无法将字符串解析为 Java 日期

Java 任务队列、线程池和带有回调的线程,用于通知新任务何时可以启动