作为初学者,我正在学习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。
1条答案
按热度按时间5uzkadbs1#
这个
Executors.newFixedThreadPool
返回一个ExecutorService
; 一个接口,它不公开(可能是很好的理由)这样的方法setMaximumPoolSize
以及setCorePoolSize
.如果创建类型为
Executors.newFixedThreadPool
,此池在应用程序的生存期内应保持固定。如果您想要一个可以相应地调整大小的池,那么应该使用Executors.newCachedThreadPool()
相反。据我所知,executors.newfixedthreadpool(3)创建了一个corepoolsize-3(…)的池
看执行
newFixedThreadPool
可以看出:和
所以当你经过的时候
3
到Executors.newFixedThreadPool
构造函数,设置corePoolSize
以及maximumPoolSize
至3
.(…)当我们继续通过池执行任务时,线程将被创建到3,然后当基础队列大小达到100并且仍然提交新任务时,这就是maxpoolsize进入图片的地方,线程被缩放到从corepoolsize现在达到maxpoolsize。
实际上,这不是很准确,但我稍后会详细解释。现在阅读
Executors.newFixedThreadPool
它指出:创建一个线程池,该线程池重用在共享无边界队列上运行的固定数量的线程。在任何时候,线程最多都是活动的处理任务。如果在所有线程都处于活动状态时提交其他任务,它们将在队列中等待,直到有线程可用。
所以池没有伸缩性(除非您显式地这样做)。
当执行上述程序时,我可以看到队列大小达到b/w 12000-20000,如果是这种情况,那么getpoolsize()必须打印大于corepoolsize的值,因为maxpoolsize设置为10,但是每次它只打印3(这就是corepoolsize)为什么会发生这种情况?正如我们所期望的,它可以扩展到maxpoolsize。
不,这不准确,如果你打印
pool.getMaximumPoolSize()
它会回来的10
如预期,呼叫pool.setMaximumPoolSize(10);
不会更改corepoolsize大小。但是,如果你这样做pool.setCorePoolSize(10);
您将增加游泳池以处理10
同时执行线程。这个
this.maximumPoolSize
它只定义池应同时处理的线程数的上限,不改变池的当前大小。为什么池不动态地增加其大小?
再深入一点
newFixedThreadPool
实现时,可以看到池是用任务队列初始化的new LinkedBlockingQueue<Runnable>()
大小等于Integer.MAX_VALUE
. 看看这个方法execute
在评论中可以看到以下内容:如果仔细阅读第2点和第3点,可以推断只有当任务不能添加到队列时,池才会创建比corepoolsize指定的线程更多的线程。自从
Executors.newFixedThreadPool
使用队列Integer.MAX_VALUE
除非显式设置corePoolSize
与pool.setCorePoolSize
.所有这些都是不必关心的实现细节。因此,为什么
Executors
接口不公开方法,例如setMaximumPoolSize
.从threadpoolexecutor文档中可以看到:
核心和最大池大小
threadpoolexecutor将根据corepoolsize(请参阅getcorepoolsize())和maximumpoolsize(请参阅getmaximumpoolsize())设置的边界自动调整池大小(请参阅getpoolsize())。在方法execute(java.lang.runnable)中提交新任务时,如果运行的线程少于corepoolsize,则会创建一个新线程来处理请求,即使其他工作线程处于空闲状态。如果运行的线程多于corepoolsize,但少于maximumpoolsize,则仅当队列已满时才会创建新线程。通过将corepoolsize和maximumpoolsize设置相同,可以创建固定大小的线程池。通过将maximumpoolsize设置为一个基本上没有边界的值,例如integer.max\u value,您可以允许池容纳任意数量的并发任务。最典型的是,核心池和最大池大小仅在构造时设置,但也可以使用setcorepoolsize(int)和setmaximumpoolsize(int)动态更改。
这基本上证实了池没有动态更新其大小的原因。