我正在使用ExecutorService创建一个固定的线程池并启动几个工作线程,这些线程监听发生的事情,然后完成他们的工作.
但有时我想增加或减少同时运行的线程数量,以便微调应用程序的性能(无需重新启动应用程序或终止任何当前运行的线程).
我应该创建自己的线程池,还是有办法让一个池的大小改变,以便在必要时处理工作人员的开始/停止.
解决方法:
However sometimes I would like to increase or decrease the amount of
threads that are running at the same time in order to fine tune the
perfomance of the app (without restarting the app or killing any
currently running threads).
如果你的意思是使用某种工具或其他东西动态更改,那么我不确定,但你可以设置一些代码逻辑来控制.
您可以使用java.util.concurrent.ThreadPoolExecutor并使用CorePoolSize和MaxPoolSize属性来控制线程池.
corePoolSize和maximumPoolSize:
> ThreadPoolExecutor将根据corePoolSize(请参阅getCorePoolSize())和maximumPoolSize(请参阅getMaximumPoolSize())设置的边界自动调整池大小(请参阅getPoolSize()).
>在方法execute(java.lang.Runnable)中提交新任务时,并且运行的线程少于corePoolSize,即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求.
>如果有多个corePoolSize但运行的maximumPoolSize线程少于,则只有在队列已满时才会创建新线程.
但在您决定之前,我建议您阅读下面摘自ThreadPoolExecutor的Java文档.
However, programmers are urged to use the more convenient Executors
factory methods Executors.newCachedThreadPool() (unbounded thread
pool, with automatic thread reclamation),
Executors.newFixedThreadPool(int) (fixed size thread pool) and
Executors.newSingleThreadExecutor() (single background thread), that
preconfigure settings for the most common usage scenarios.
代码示例:
请参考下面的代码示例.通过阅读代码和浏览Java文档,您可以理解大多数事项.然而,事实可能并不明显
>我们使用ArrayBlockingQueue获取20个容量的有界队列(您可以根据需要决定队列容量).因此,一旦队列中有超过20个任务等待,将创建新线程但最多为maxPoolSize.
>基于负载,我们增加了核心池线程的数量,这意味着更多线程将处理您的任务,因此任务排队的机会更少.但您也可以使用maxPoolSize.
您可以阅读ThreadPoolExecutor的“排队”部分,并根据您的要求决定其他队列.
ThreadPoolExecutor.setCorePoolSize(int)
设置核心线程数.这将覆盖构造函数中设置的任何值.如果新值小于当前值,则当下一个空闲时,多余的现有线程将被终止.如果需要更大,则新线程将启动以执行任何排队任务.
//Read Java docs for details about construcutor...
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 100, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20));
Runnable runnable = new Runnable() {
@Override
public void run() {
//Do your task...
}
};
executeTasks(poolExecutor, runnable, false, false); //Compute last 2 parameters as you need and pass on required values.
public static void executeTasks(ThreadPoolExecutor poolExecutor, Runnable runnable, boolean isUnderLoad, boolean isOverLoad){
if(isOverLoad && isUnderLoad){
//Handle this situation, this should not be allowed, probably a coding bug can result this...
}
poolExecutor.submit(runnable);
if(isUnderLoad){
poolExecutor.setCorePoolSize(5);
}
if(isOverLoad){
poolExecutor.setCorePoolSize(20);
}
}