当前位置: 首页 > 知识库问答 >
问题:

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

谢华彩
2023-03-14

我在Java 6的ThreadPoolExecutor中遇到了一个奇怪的问题。当我不时地动态更改corePoolSize时,我观察到线程池并没有处理它应该处理的那个么多任务。

例如,如果我有4个作为corePoolSize,并且队列中有很多任务等待,那么执行器最多处理3个,有时甚至处理2个。

在调查这个问题时,我注意到当我增加或减少corePoolsize时,我从未更改过maxPoolsize。从我的应用程序开始,它一直是1。

在Java文档中从未发现一条语句提到maxPoolSize小于core的影响。

然后当我检查源代码时,我注意到在costructor和setCorePoolSize方法中,如果抛出非法的ArgumentException,它会在哪里检查max umPoolSize小于corePoolSize。检查下面的代码。

建造师

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个答案

柯良骏
2023-03-14

我想,你是对的,应该有这样的测试

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

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

 类似资料:
  • 在Thymeleaf中执行简单-的最佳方法是什么? 我想在Thymeleaf中达到与 你能提出一个更好的方法来实现它吗?

  • 问题内容: 问题答案: 每当Python解释器读取源文件时,它就会做两件事: 它设置了一些特殊变量,例如,然后 它执行文件中找到的所有代码。 让我们看看它是如何工作的,以及它与你有关我们在Python脚本中经常看到的检查问题的关系。 代码样例 让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。假设以下文件位于。 特殊变量 当Python交互程序读取源文件时,它首先定义了一些特殊变量。在这种情

  • 在下面的示例中:https://github.com/confluentinc/kafka-streams-examples/blob/5.1.0-post/src/main/java/io/confluent/examples/streams/pageViewRegionexample.java有一个KStream和KTable连接。 在驱动程序https://github.com/conflu

  • 问题内容: 在Java中,当对象将要进行垃圾回收时(因此无法访问),在对象(覆盖它)上调用。但是,如果终结器使对象再次可访问,该怎么办呢? 问题答案: 在再次变得不可访问之前,将不会收集该对象。 根据JavaDoc,将不会再次调用finalize()。

  • 问题内容: 如果我使用注释构造函数参数,但Json没有指定该属性,会发生什么情况。构造函数得到什么值? 如何区分具有空值的属性和JSON中不存在的属性? 问题答案: 总结程序员Bruce和StaxMan的出色答案: 构造函数引用的缺少的属性会分配一个Java定义的默认值。 您可以使用setter方法来区分隐式或显式设置的属性。Setter方法仅针对具有显式值的属性调用。设置方法可以跟踪是否使用布尔

  • 本文向大家介绍如果leader crash时,ISR为空怎么办?相关面试题,主要包含被问及如果leader crash时,ISR为空怎么办?时的应答技巧和注意事项,需要的朋友参考一下 kafka在Broker端提供了一个配置参数:unclean.leader.election,这个参数有两个值: true(默认):允许不同步副本成为leader,由于不同步副本的消息较为滞后,此时成为leader,