首页 文章

如果maximumPoolSize小于corePoolSize怎么办? Java 6中可能存在的错误?

提问于
浏览
1

我遇到了Java 6的ThreadPoolExecutor一个奇怪的问题 . 我不时地动态更改了corePoolSize,我观察到线程池没有处理应该完成的任务 .

例如,如果我有4个corePoolSize并且队列中有许多任务等待,那么执行程序最多处理3个,有时甚至是2个 .

在调查问题的时候,我注意到当我增加或减少corePoolSize时我从未改变过maxPoolSize . 从我的申请开始,它一直是1 .

从来没有在Java的文档中找到一个声明,提到maxPoolSize的效果小于核心 .

然后当我检查源代码时,我注意到在costructor和setCorePoolSize方法中,它会检查maximumPoolSize小于corePoolSize的位置,如果是这样,则抛出illegalArgumentException . 看看下面的代码 .

构造函数

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler
) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
            throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

设置最大池大小

public void setMaximumPoolSize(int maximumPoolSize) {
    if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
        throw new IllegalArgumentException();
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        int extra = this.maximumPoolSize - maximumPoolSize;
        this.maximumPoolSize = maximumPoolSize;
        if (extra > 0 && poolSize > maximumPoolSize) {
            try {
                Iterator<Worker> it = workers.iterator();
                while (it.hasNext() &&
                       extra > 0 &&
                       poolSize > maximumPoolSize) {
                    it.next().interruptIfIdle();
                    --extra;
                }
            } catch (SecurityException ignore) {
                // Not an error; it is OK if the threads stay live
            }
        }
    } finally {
        mainLock.unlock();
    }
}

所以,显然这是一个不受欢迎的情况 . 但是没有检查setCorePoolSize,导致maximumPoolSize最终小于corePoolSize,并且没有记录这种情况的影响 .

设置核心池大小

public void setCorePoolSize(int corePoolSize) {
    if (corePoolSize < 0)
        throw new IllegalArgumentException();
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        int extra = this.corePoolSize - corePoolSize;
        this.corePoolSize = corePoolSize;
        if (extra < 0) {
            int n = workQueue.size(); // don't add more threads than tasks
            while (extra++ < 0 && n-- > 0 && poolSize < corePoolSize) {
                Thread t = addThread(null);
                if (t == null)
                    break;
            }
        }
        else if (extra > 0 && poolSize > corePoolSize) {
            try {
                Iterator<Worker> it = workers.iterator();
                while (it.hasNext() &&
                       extra-- > 0 &&
                       poolSize > corePoolSize &&
                       workQueue.remainingCapacity() == 0)
                    it.next().interruptIfIdle();
            } catch (SecurityException ignore) {
                // Not an error; it is OK if the threads stay live
            }
        }
    } finally {
        mainLock.unlock();
    }
}

难道你不认为应该有一种机制阻止这种情况结束吗?

1 回答

  • 0

    我想,你是对的,应该有一个类似的测试

    if (corePoolSize < 0 || corePoolSize > maxPoolSize)
        throw new IllegalArgumentException();
    

    但您可以在调用 setCorePoolSize 之前轻松测试此项,并在必要时调整最大池大小 . 即使有这样的测试,你也必须在调用 setCorePoolSize 之前检查最大池大小,以避免得到 IllegalArgumentException ...

相关问题