gpt4 book ai didi

java - 使用 ThreadPoolExecutor 缩放 maxPoolSize;为什么池不会动态增加其大小?

转载 作者:行者123 更新时间:2023-12-03 12:51:06 25 4
gpt4 key购买 nike

我作为初学者正在学习java中的线程和并发包,并且我已经阅读了有关 ThreadPoolExecutor 的文档以了解 getPoolSize()getCorePoolSize() 之间的区别, getMaxPoolSize() 并尝试在代码中实现相同的功能。

背景知识

据我了解,Executors.newFixedThreadPool(3) 创建一个池corePoolSize=3 并且当我们继续通过池执行任务时,将创建线程直到 3,然后当底层队列大小达到 100 并且仍然提交新任务时,这就是 maxPoolSize 出现的地方,线程现在从 corePoolSize 扩展到 maxPoolSize .

public class Test {

static ThreadPoolExecutor pool=(ThreadPoolExecutor)Executors.newFixedThreadPool(3);

public static void main(String k[]) throws InterruptedException{
BlockingQueue<Runnable> queue=pool.getQueue();
pool.execute(()->{
for(int b=0;b<10;b++)
System.out.println("Hello "+b);
});
pool.execute(()->{
for(int b=0;b<10;b++)
System.out.println("Hello "+b);
});
pool.setMaximumPoolSize(10); //Setting maxPoolSize

for(int j=0;j<20000;j++)
pool.execute(()->{
for(int b=0;b<100;b++){
System.out.println("Hello "+b);
System.out.println("Queue size "+queue.size()+" "+"and pool size "+pool.getPoolSize());
}
});
}

执行上述程序时,我可以看到队列大小达到 b/w 12000-20000,如果是这种情况,那么 getPoolSize() 必须打印大于 corePoolSize 的值,因为设置了 maxPoolSize到 10 但每次它只会打印 3(这是 corePoolSize) 为什么会发生这种情况?正如我们预期的那样,它可以扩展到 maxPoolSize。

Eclipse console

最佳答案

Executors.newFixedThreadPool返回 ExecutorService ;一个不公开(并且可能有充分理由)方法的接口(interface),例如 setMaximumPoolSizesetCorePoolSize .

如果您创建 Executors.newFixedThreadPool 类型的池,此池应在应用程序的生命周期内保持固定。如果您想要一个可以相应调整其大小的池,您应该使用 Executors.newCachedThreadPool()而是。

From my understanding, Executors.newFixedThreadPool(3) creates a poolwith corePoolSize-3 (...)

newFixedThreadPool的实现可以看出:

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}

所以当你通过 3Executors.newFixedThreadPool构造函数,你设置 both corePoolSizemaximumPoolSize3 .

(...) and as we keep executing tasks via pool, threads will be created until3 and then when the underlying queue size reaches 100 and new tasksare still submitted then that's where maxPoolSize comes into pictureand threads are scaled to reach maxPoolSize from corePoolSize now.

其实这个不是很准确,后面会详细解释。现在阅读 Executors.newFixedThreadPool 的 Java 文档它指出:

Creates a thread pool that reuses a fixed number of threads operatingoff a shared unbounded queue. At any point, at most nThreads threadswill be active processing tasks. If additional tasks are submittedwhen all threads are active, they will wait in the queue until athread is available.

因此,池没有缩放(除非您明确这样做)。

When the above program is executed,i could see the queue size reachingb/w 12000-20000, if this the case then getPoolSize() must print thevalue greater than corePoolSize as maxPoolSize is set to 10 buteverytime it would only print 3(which is corePoolSize) why does thishappen ? as we expect it to scale upto maxPoolSize.

不,这不准确,如果您打印 pool.getMaximumPoolSize()它将返回 10不出所料,调用pool.setMaximumPoolSize(10);不会改变 corePoolSize 的大小。但是,如果您这样做 pool.setCorePoolSize(10);您将增加池以能够处理 10同时线程。

this.maximumPoolSize只是定义了池应该同时处理多少线程的上限,它不会改变池的当前大小。

为什么池不动态增加其大小?

深入了解newFixedThreadPool实现,可以看到Pool初始化了一个任务队列new LinkedBlockingQueue<Runnable>()大小等于 Integer.MAX_VALUE .看方法execute可以在评论中阅读以下内容:

/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/

如果仔细阅读第 2 点和第 3 点,可以推断只有当无法将任务添加到队列时,池才会创建比 corePoolSize 指定的线程更多的线程。自从 Executors.newFixedThreadPool使用带有 Integer.MAX_VALUE 的队列您无法看到池动态分配更多资源,除非明确设置 corePoolSizepool.setCorePoolSize .

所有这些都是不需要关心的实现细节。因此,为什么 Executors接口(interface)不暴露方法如 setMaximumPoolSize .

来自 ThreadPoolExecutor可以阅读的文档:

核心和最大池大小

A ThreadPoolExecutor will automatically adjust the pool size (seegetPoolSize()) according to the bounds set by corePoolSize (seegetCorePoolSize()) and maximumPoolSize (see getMaximumPoolSize()).When a new task is submitted in method execute(java.lang.Runnable),and fewer than corePoolSize threads are running, a new thread iscreated to handle the request, even if other worker threads are idle.If there are more than corePoolSize but less than maximumPoolSizethreads running, a new thread will be created only if the queue isfull. By setting corePoolSize and maximumPoolSize the same, you createa fixed-size thread pool. By setting maximumPoolSize to an essentiallyunbounded value such as Integer.MAX_VALUE, you allow the pool toaccommodate an arbitrary number of concurrent tasks. Most typically,core and maximum pool sizes are set only upon construction, but theymay also be changed dynamically using setCorePoolSize(int) andsetMaximumPoolSize(int).

这基本上证实了为什么池没有动态更新其大小。

关于java - 使用 ThreadPoolExecutor 缩放 maxPoolSize;为什么池不会动态增加其大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65512477/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com