核心池大小与ThreadPoolExecutor中的最大池大小
当我们使用ThreadPoolExecutor进行交谈时,核心池大小和最大池大小究竟有什么区别? 可以用一个例子来解释吗?
从这个博客文章 :
以这个例子。 启动线程池大小为1,核心池大小为5,最大池大小为10,队列为100。
随着请求的进入,线程将被创build到5,然后任务将被添加到队列中,直到达到100.当队列已满时,新线程将被创build到
maxPoolSize
。 一旦所有的线程都在使用中,并且队列已满,任务将被拒绝。 随着队列的减less,活动线程数量也随之减less。
从文档 :
当在方法execute(java.lang.Runnable)中提交新任务并且less于corePoolSize线程正在运行时,即使其他工作线程处于空闲状态,也会创build一个新线程来处理该请求。 如果有多于corePoolSize但小于maximumPoolSize线程正在运行,则只有在队列已满时才会创build一个新线程。
此外:
通过设置corePoolSize和maximumPoolSize相同,您可以创build一个固定大小的线程池。 通过将maximumPoolSize设置为基本上无界的值(例如Integer.MAX_VALUE),可以让池容纳任意数量的并发任务。 最典型的是,核心和最大池大小只在构build时设置,但也可以使用setCorePoolSize(int)和setMaximumPoolSize(int)dynamic更改。
如果您决定手动创buildThreadPoolExecutor
而不是使用Executors
工厂类,则需要使用其构造函数之一来创build和configuration一个。 这个类最广泛的构造函数是:
public ThreadPoolExecutor( int corePoolSize, int maxPoolSize, long keepAlive, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler );
正如你所看到的,你可以configuration:
- 核心池大小(线程池将尝试坚持的大小)。
- 最大池大小。
- 保持活动时间,这是一个空闲线程有资格被拆除的时间。
- 工作队列保存等待执行的任务。
- 拒绝任务提交时应用的策略。
限制排队任务的数量
限制正在执行的并发任务的数量,根据可预测性和稳定性,为您的应用程序及其执行环境提供巨大的好处:无限制的线程创build将最终耗尽运行时资源,您的应用程序可能会因此受到影响,严重的性能问题甚至可能导致应用程序不稳定。
这只是解决问题的一部分的一个解决scheme:您正在限制正在执行的任务数量,但不限制可以提交和排队等待以后执行的作业数量。 应用程序将在稍后遇到资源短缺,但如果提交率一直超出执行率,则最终会遇到这种情况。
解决这个问题的方法是:为执行者提供一个阻塞队列来保存等待的任务。 在队列填满的情况下,提交的任务将被“拒绝”。 当任务提交被拒绝时, RejectedExecutionHandler
被调用,这就是为什么被拒绝的动词被引用在前一个项目中的原因。 您可以实施自己的拒绝政策,或使用框架提供的内置政策之一。
默认的拒绝策略是执行程序抛出一个RejectedExecutionException
。 但是,其他内置策略可让您:
- 默默地放弃工作。
- 丢弃最古老的工作,并尝试重新提交最后一个。
- 在调用者的线程上执行被拒绝的任务。
您可以在javadoc中find术语corepoolsize和maxpoolsize的定义。 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
上面的链接有你的问题的答案。 但是,只是为了说清楚。 应用程序将继续创build线程,直到达到corePoolSize。 我认为这里的想法是这些线程应该足以处理任务的stream入。 如果在创buildcorePoolSize线程后出现新任务,任务将排队。 一旦队列满了,执行程序将开始创build新的线程。 这是一种平衡。 其实质意味着任务的stream入不仅仅是处理能力。 所以,Executor会再次开始创build新线程,直到达到最大线程数。 同样,当且仅当队列已满时才会创build新线程。