背景
前面我们了解到,Exector是包含在Service中,Service中关于Execute的配置和相关代码如下:
<Service name="Catalina">
<!-- 1. 属性说明
name:Service的名称
-->
<!--2. 一个或多个excecutors --> // 看这里
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
</Service>
Service中executors相关方法
/**
* Adds a named executor to the service
* @param ex Executor
*/
@Override
public void addExecutor(Executor ex) {
synchronized (executors) {
if (!executors.contains(ex)) {
executors.add(ex);
if (getState().isAvailable()) {
try {
ex.start(); // 启动
} catch (LifecycleException x) {
log.error(sm.getString("standardService.executor.start"), x);
}
}
}
}
}
/**
* Retrieves all executors
* @return Executor[]
*/
@Override
public Executor[] findExecutors() {
synchronized (executors) {
Executor[] arr = new Executor[executors.size()];
executors.toArray(arr);
return arr;
}
}
/**
* Retrieves executor by name, null if not found
* @param executorName String
* @return Executor
*/
@Override
public Executor getExecutor(String executorName) {
synchronized (executors) {
for (Executor executor: executors) {
if (executorName.equals(executor.getName()))
return executor;
}
}
return null;
}
/**
* Removes an executor from the service
* @param ex Executor
*/
@Override
public void removeExecutor(Executor ex) {
synchronized (executors) {
if ( executors.remove(ex) && getState().isAvailable() ) {
try {
ex.stop(); // 停止
} catch (LifecycleException e) {
log.error(sm.getString("standardService.executor.stop"), e);
}
}
}
}
和Server、Service实现一样,StandardThreadExecutor也是即成了生命周期接口LifecycleMBeanBase;然后实现Executor接口。

Execute接口设计
1.Tomcat希望将Executor也纳入Lifecycle生命周期管理,所以实现了Lifecycle接口
2.引入超时机制:当work queue满时,会等待指定的时间,如果超时将抛出RejectedExectionException,所以加了个void execute(Runnable command, long timeout, TimeUnit unit)方法。
package org.apache.catalina;
import java.util.concurrent.TimeUnit;
public interface Executor extends java.util.concurrent.Executor, Lifecycle {
public String getName();
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the <code>Executor</code> implementation.
* If no threads are available, it will be added to the work queue.
* If the work queue is full, the system will wait for the specified
* time until it throws a RejectedExecutionException
*
* @param command the runnable task
* @param timeout the length of time to wait for the task to complete
* @param unit the units in which timeout is expressed
*
* @throws java.util.concurrent.RejectedExecutionException if this task
* cannot be accepted for execution - the queue is full
* @throws NullPointerException if command or unit is null
*
* @deprecated Unused. Will be removed in Tomcat 10.1.x onwards.
*/
@Deprecated
void execute(Runnable command, long timeout, TimeUnit unit);
}
StandardThreadExecutor的实现
Executor的所有实现都要支持以下属性
- className:实现的类。实现必须实现 org.apache.catalina.Executor接口。此接口确保可以通过其name属性引用对象并实现Lifecycle,以便可以使用容器启动和停止对象。className的默认值org.apache.catalina.core.StandardThreadExecutor
- name:用于server.xml中的其他位置引用此池的名称。该名称是必须的,且唯一的
StandardThreadExecutor属性
- threadPriority:(int)执行程序中线程的线程优先级,默认为5(Thread.NORM_PRIORITY常量的值)
- daemon:(boolean)线程是否应该是守护程序线程,默认是true
- namePrefix:(字符串)执行程序创建的每个线程的名称前缀。单个线程的线程名称将是namePrefix + threadNumber
- maxTheads:线程中活动线程的最大数量,默认为200
- minSpareThreads:最小线程数始终保持活跃状态,默认25
- maxIdleTime:空闲线程关闭之前的毫秒数
- maxQueueSize:在我们拒绝之前可以排队等待执行的可运行任务的最大数量
- prestartminSpareThreads:是否在启动Executor时启动minSpareThreads,默认为false
- threadRenewalDelay:如果配置了ThreadLocalLeakPreventionListener,它将通知此执行程序有关已停止的上下文。上下文停止后,池中的线程将被更新。
Lifecycle模版方法
-
先看下核心变量:
private TaskQueue taskqueue = null; protected ThreadPoolExecutor executor = null;
-
initInternal和destroyInternal默认父类实现
@Override protected void initInternal() throws LifecycleException { super.initInternal(); } @Override protected void destroyInternal() throws LifecycleException { super.destroyInternal(); }
-
startInternal方法
这个方法中中,我们不难看出,就是初始化taskqueue,同时构造ThreadPoolExecutor的实例,后面的StardardThreadExecutor的实现本质上通过ThreadPoolExecutor实现的。
/**
* Start the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
taskqueue = new TaskQueue(maxQueueSize);
TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);
executor.setThreadRenewalDelay(threadRenewalDelay);
if (prestartminSpareThreads) {
executor.prestartAllCoreThreads();
}
taskqueue.setParent(executor);
setState(LifecycleState.STARTING);
}
- stopInternal方法
关闭线程池后置为null,方便GC回收
/**
* Stop the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
@Override
protected void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
if (executor != null) {
executor.shutdownNow();
}
executor = null;
taskqueue = null;
}
核心executor方法
本质上就是调用ThreadPoolExecutor实例相关方法
@Override
@Deprecated
public void execute(Runnable command, long timeout, TimeUnit unit) {
if (executor != null) {
executor.execute(command,timeout,unit);
} else {
throw new IllegalStateException(sm.getString("standardThreadExecutor.notStarted"));
}
}
@Override
public void execute(Runnable command) {
if (executor != null) {
// Note any RejectedExecutionException due to the use of TaskQueue
// will be handled by the o.a.t.u.threads.ThreadPoolExecutor
executor.execute(command);
} else {
throw new IllegalStateException(sm.getString("standardThreadExecutor.notStarted"));
}
}
动态调整线程池
我们还注意到StandardThreadExecutor还实现了ResizableExecutor,从名称上大概能推测出它是希望实现对线程池的动态调整,所以封装了该接口
public interface ResizableExecutor extends Executor {
/**
* Returns the current number of threads in the pool.
*
* @return the number of threads
*/
public int getPoolSize();
public int getMaxThreads();
/**
* Returns the approximate number of threads that are actively executing
* tasks.
*
* @return the number of threads
*/
public int getActiveCount();
public boolean resizePool(int corePoolSize, int maximumPoolSize);
public boolean resizeQueue(int capacity);
}
前三个方法比较简单,可以看下后两个方法
@Override
public boolean resizePool(int corePoolSize, int maximumPoolSize) {
if (executor == null) {
return false;
}
executor.setCorePoolSize(corePoolSize);
executor.setMaximumPoolSize(maximumPoolSize);
return true;
}
@Override
public boolean resizeQueue(int capacity) {
return false;
}