1

java 是否保证 corepool 线程将始终在 ThreadPoolExecutor 中保持活动状态?

我多次运行我的测试代码,但似乎不能保证。

我尝试使用 allowCoreThreadTimeOut=true 和 allowCoreThreadTimeOut = false。然而,行为并没有改变。

这是我的测试代码。请尝试使用 noOfTaskToRun 1 和 4 的两个不同值。

public static void main(String[] args) {
    int noOfTaskToRun = 1;
    ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 2000, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
    executor.allowCoreThreadTimeOut(false);
    List<Thread> threads = new ArrayList<Thread>();

    for(int i = 0; i<noOfTaskToRun ; i++)
        threads.add(new Thread("thread" + i) {
        public void run() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
    for (Thread thread : threads) {
        executor.execute(thread);
    }

    System.out.println("Before executor.getActiveCount(): "+ executor.getActiveCount());

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println("After executor.getActiveCount(): "+ executor.getActiveCount());
}

我将 keepAliveTime 修改为 2000。即使现在线程正在超时。

4

4 回答 4

1

我实际上不是 100% 确定,但getActiveCount()不是你想的那样,我想。文档说:“返回正在积极执行任务的线程的大致数量。” 所以,我的猜测是空闲线程不包含在该数字中,但仍然可以存活。您可能想要的是getPoolSize():“返回池中的当前线程数。”

另外:如果您的任务睡眠 5 秒,并且您给所有任务 5 秒超时,那么超时后有多少任务完成将是非常随机的......

于 2013-09-02T13:37:10.490 回答
0

据我了解不会。我也看到了代码(JDK 6),似乎如果线程数在执行程序的生命周期中少于 corepoolthreads ,则它可以保证,但是一旦超过限制,就不能保证核心线程将保持活动状态。

我尝试使用 allowCoreThreadTimeOut = false 运行。即使这样,如果线程数超过 coreThreadPoolSize,线程也会死亡。但是,如果线程数仍然小于 coreThreadPoolSize,那么它们仍然活着。

我认为原因在于 ThreadPoolExecutor 类的这两个方法。当队列为空时,workerCanExit 会检查 coreThreadPoolSize 或 allowCoreThreadTimeOut 的值,这就是线程超时的原因。

    Runnable getTask() {
    for (;;) {
        try {
            int state = runState;
            if (state > SHUTDOWN)
                return null;
            Runnable r;
            if (state == SHUTDOWN)  // Help drain queue
                r = workQueue.poll();
            else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
                r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
            else
                r = workQueue.take();
            if (r != null)
                return r;
            if (workerCanExit()) {
                if (runState >= SHUTDOWN) // Wake up others
                    interruptIdleWorkers();
                return null;
            }
            // Else retry
        } catch (InterruptedException ie) {
            // On interruption, re-check runState
        }
    }
}

    private boolean workerCanExit() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    boolean canExit;
    try {
        canExit = runState >= STOP ||
            workQueue.isEmpty() ||
            (allowCoreThreadTimeOut &&
             poolSize > Math.max(1, corePoolSize));
    } finally {
        mainLock.unlock();
    }
    return canExit;
}
于 2013-09-02T11:57:58.737 回答
0

不,它不能保证。例如,其中一个构造函数的 javadoc说:

" corePoolSize- 保留在池中的线​​程数,即使它们是空闲的,除非allowCoreThreadTimeOut已设置"

显而易见的含义是,如果您调用allowCoreThreadTimeOut(true),那么即使是核心池线程也可能超时。

于 2013-09-02T12:05:38.477 回答
0

根据 ThreadPoolExecutor 文档,核心线程将留在池中,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut 标志。

核心线程死亡的另一种情况是在任务执行期间抛出异常。在这种情况下,该线程将被替换为新线程。

于 2013-09-02T12:10:27.900 回答