Tomcat 系列篇八-介绍下 Tomcat 里的线程池用处

线程池在 Tomcat 中也是非常重要的工具,这里我们简单介绍下 Tomcat 中的线程池,在 container 的启动过程中
org.apache.catalina.core.ContainerBase#initInternal

@Override
    protected void initInternal() throws LifecycleException {
        reconfigureStartStopExecutor(getStartStopThreads());
        super.initInternal();
    }

这里先会获取线程数,

@Override
public int getStartStopThreads() {
    return startStopThreads;
}

默认的 ContainerBase 的设置线程数是 1

private int startStopThreads = 1;

那就会按照 org.apache.catalina.core.ContainerBase#reconfigureStartStopExecutor 来设置线程池类型

private void reconfigureStartStopExecutor(int threads) {
    if (threads == 1) {
        // Use a fake executor
        if (!(startStopExecutor instanceof InlineExecutorService)) {
            startStopExecutor = new InlineExecutorService();
        }
    } else {
        // Delegate utility execution to the Service
        Server server = Container.getService(this).getServer();
        server.setUtilityThreads(threads);
        startStopExecutor = server.getUtilityExecutor();
    }
}

此时线程池类型是 null 也就会走到上一个分支中,new 一个 InlineExecutorService 出来
前面的这些其实是在 StandardEngine 初始化过程中,也就是 initInternal 时候进行的
然后具体的使用是在 startInternal 开始方法中,

// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
    results.add(startStopExecutor.submit(new StartChild(child)));
}

会获取当前 StandardEngine 的子组件提交给线程池进行启动
而这个 StartChild 也比较简单

private static class StartChild implements Callable<Void> {

    private Container child;

    public StartChild(Container child) {
        this.child = child;
    }

    @Override
    public Void call() throws LifecycleException {
        child.start();
        return null;
    }
}

就是调用子组件的 start 方法,
在 org.apache.tomcat.util.threads.InlineExecutorService 的父类,java.util.concurrent.AbstractExecutorService 中先会把 Callable 包装成 FutureTask

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

然后进行执行,

@Override
public void execute(Runnable command) {
    synchronized (lock) {
        if (shutdown) {
            throw new RejectedExecutionException();
        }
        taskRunning = true;
    }
    command.run();
    synchronized (lock) {
        taskRunning = false;
        if (shutdown) {
            terminated = true;
            lock.notifyAll();
        }
    }
}

这个就是我们 startStopExecutor 的主要作用,帮我们启动子组件
对于 Container 来说启动的就是 host,而其实 host 也是继承了 ContainerBase 的,后面可以再继续介绍下