`
悲剧了
  • 浏览: 145502 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

tomcat源码学习--线程池

阅读更多
写个前言:
通常大家知道tomcat的线程池是可以配置的,去找到conf下面的的server.xml就可以搞定,先配置指定参数
引用

  <Service name="Catalina">
 
    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->

在配置连接器使用它,注释中都给出了例子
引用

  <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->         


    但现在不是想说这个,是想看看tomcat源码里的线程池,只看配置文件没啥意义,不好玩
开始->>
  首先看tomcat的源码,ThreadPool里面的成员变量
    private static Log log = LogFactory.getLog(ThreadPool.class);

    private static StringManager sm =
        StringManager.getManager("org.apache.tomcat.util.threads.res");

    private static boolean logfull=true;

    /*
     * Default values ...
     */
    public static final int MAX_THREADS = 200;
    public static final int MAX_THREADS_MIN = 10;
    public static final int MAX_SPARE_THREADS = 50;
    public static final int MIN_SPARE_THREADS = 4;
    public static final int WORK_WAIT_TIMEOUT = 60*1000;

    /*
     * Where the threads are held.
     */
    protected ControlRunnable[] pool = null;

    /*
     * A monitor thread that monitors the pool for idel threads.
     */
    protected MonitorRunnable monitor;


    /*
     * Max number of threads that you can open in the pool.
     */
    protected int maxThreads;

    /*
     * Min number of idel threads that you can leave in the pool.
     */
    protected int minSpareThreads;

    /*
     * Max number of idel threads that you can leave in the pool.
     */
    protected int maxSpareThreads;

    /*
     * Number of threads in the pool.
     */
    protected int currentThreadCount;

    /*
     * Number of busy threads in the pool.
     */
    protected int currentThreadsBusy;

    /*
     * Flag that the pool should terminate all the threads and stop.
     */
    protected boolean stopThePool;

    /* Flag to control if the main thread is 'daemon' */
    protected boolean isDaemon=true;

    /** The threads that are part of the pool.
     * Key is Thread, value is the ControlRunnable
     */
    protected Hashtable threads=new Hashtable();

    protected Vector listeners=new Vector();

    /** Name of the threadpool
     */
    protected String name = "TP";

    /**
     * Sequence.
     */
    protected int sequence = 1;

    /**
     * Thread priority.
     */
    protected int threadPriority = Thread.NORM_PRIORITY;


    /**
     * Constructor.
     */    
    public ThreadPool() {
        maxThreads = MAX_THREADS;
        maxSpareThreads = MAX_SPARE_THREADS;
        minSpareThreads = MIN_SPARE_THREADS;
        currentThreadCount = 0;
        currentThreadsBusy = 0;
        stopThePool = false;
    }

  构造函数里面默认指定了线程池配置的东西,这里的每个参数就不说了,tomcat用在这个类里面即对线程池用到的参数使用变量+常量 形式让这个可配置型增加,也好理解修改

构造线程池的策略是什么呢?一个Hashtable来键值对存储

引用

/** The threads that are part of the pool.
     * Key is Thread, value is the ControlRunnable
     */
    protected Hashtable threads=new Hashtable();


   public void addThread( Thread t, ControlRunnable cr ) {
        threads.put( t, cr );
        for( int i=0; i<listeners.size(); i++ ) {
            ThreadPoolListener tpl=(ThreadPoolListener)listeners.elementAt(i);
            tpl.threadStart(this, t);
        }
    }

    public void removeThread( Thread t ) {
        threads.remove(t);
        for( int i=0; i<listeners.size(); i++ ) {
            ThreadPoolListener tpl=(ThreadPoolListener)listeners.elementAt(i);
            tpl.threadEnd(this, t);
        }
    }

    里面的key经过了多层的包装,他里面封装了很多信息ThreadWithAttributes,这一切都是通过里面的内部类ControlRunnable来实现的,内部类真是个好东西,好多复杂的东西都写在里面,是不是业务逻辑复杂,抽取成方法也不好时,可以考虑抽取内部类

    线程池启动时,做一些init工作,主要是把 pool monitor给初始化, adjustLimits()是一个防止你配置错误的validate,如果错误他会有些策略,有兴趣可以看下。完成这一切后。怎么处理线程呢?在newC的时候就
   public synchronized void start() {
    	stopThePool=false;
        currentThreadCount  = 0;
        currentThreadsBusy  = 0;
       
        adjustLimits();

        pool = new ControlRunnable[maxThreads];
/**这个内部类的构造函数
   ControlRunnable(ThreadPool p) {
            toRun = null;
            shouldTerminate = false;
            shouldRun = false;
            this.p = p;
            t = new ThreadWithAttributes(p, this);
            t.setDaemon(true);
            t.setName(p.getName() + "-Processor" + p.incSequence());
            t.setPriority(p.getThreadPriority());
            p.addThread( t, this );
	    noThData=true;
   /**这个start听复杂的,看这运行key的,但可以是ThreadWithAttributes,他继承自Thread,那么它部是空吗?不是在构造方法里面 super(r);这个方法以为着运行目标变成当前类ControlRunnable*/
            t.start();
        }
创建的数组也并没初始化这个构造函数,有这样一个方法,刚开始直接给你构造好最小个线程
   protected void openThreads(int toOpen) {

        if(toOpen > maxThreads) {
            toOpen = maxThreads;
        }
       
        for(int i = currentThreadCount ; i < toOpen ; i++) {
            /**居然还是倒着往里面赋值**/
            pool[i - currentThreadsBusy] = new ControlRunnable(this);
        }

        currentThreadCount = toOpen;
    }

**/

        openThreads(minSpareThreads);
        if (maxSpareThreads < maxThreads) {
            monitor = new MonitorRunnable(this);
        }
    }


   初始化一切搞定,当线程调用run,那么会去查找相关已经初始化的线程,再取出来,对应去运行
  public void run(Runnable r) {
        ControlRunnable c = findControlRunnable();
        c.runIt(r);
    }   



   那么着就完了吗?tomcat还提供了一个接口,你要使用线程池只需继承它是想相关的东西
/** Implemented if you want to run a piece of code inside a thread pool.
 */
public interface ThreadPoolRunnable {
    // XXX use notes or a hashtable-like
    // Important: ThreadData in JDK1.2 is implemented as a Hashtable( Thread -> object ),
    // expensive.
    
    /** Called when this object is first loaded in the thread pool.
     *  Important: all workers in a pool must be of the same type,
     *  otherwise the mechanism becomes more complex.
     */
    public Object[] getInitData();

    /** This method will be executed in one of the pool's threads. The
     *  thread will be returned to the pool.
     */
    public void runIt(Object thData[]);

}

  那么tomcat又在何处使用它了,利用eclipse工具,找到调用类PoolTcpEndpoint,里面的线程是LeaderFollowerWorkerThread还实现了ThreadPoolRunnable,感兴趣可以自己去看看

    综上所述,它实现是怎样的,先初始化一定数量的线程,他们都先睡着,线程池 runIt(listener)传入线程,传入后就不notify然后就 shouldRun = true,然后就调用传进来的线程。但是包装的东西好多啊,控制的东西验证的东西也好多,造成了这个类好大。






6
8
分享到:
评论

相关推荐

    TOMCAT的线程池源码

    《深入解析Tomcat线程池源码》 Tomcat作为一款广泛应用的开源Servlet容器,其在性能优化上有着独到之处。...对于希望提升系统性能或对服务器优化感兴趣的开发者,Tomcat线程池源码是一个不可多得的学习资源。

    apache-tomcat-7.0.39-src

    通过学习和理解这些知识点,开发者可以有效地利用Apache Tomcat 7.0.39来构建和运行Java Web应用,同时也能根据项目需求进行定制化开发。在实际工作中,根据不同的场景选择合适的Tomcat版本和配置,能确保Web应用的...

    apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src的源码

    这个压缩包包含了两个版本的Tomcat源码:apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src,这两个版本分别代表了Tomcat在不同时间点的开发状态和技术特性。 首先,让我们从Apache Tomcat 6.0.39源码开始分析。...

    apache-tomcat-7.0.64-src

    4. `src`:源代码目录,包括了Tomcat的所有模块源码,如Coyote(HTTP连接器),Jasper(JSP编译器),Juli(日志系统)等。 5. `webapps`:默认的应用程序部署目录,你可以将你的Web应用程序(WAR文件或已展开的目录...

    apache-tomcat-6.0.35和apache-tomcat-6.0.35 src

    - `apache-tomcat-6.0.35-src.zip`提供了Tomcat的完整源代码,开发者可以深入理解Tomcat的工作原理,学习Servlet容器的设计和实现,或者进行自定义扩展和调试。 - 源代码中的关键模块包括`catalina`(核心服务实现...

    apache-tomcat-8.0.47-src.zip

    - **安全管理**:通过源码学习如何配置和实现角色、权限以及访问控制。 - **部署和热更新**:Tomcat如何监测`webapps`目录下的变化,并自动部署或更新应用。 - **错误处理和日志系统**:Tomcat如何记录和报告运行时...

    tomcat-connectors-1.2.44-src.tar

    在实际开发中,我们可以通过编译源码来定制自己的连接器,比如调整线程池大小、优化网络缓冲区配置等,以适应特定的系统环境和应用需求。同时,理解连接器的工作原理,也有助于我们排查和解决Tomcat在处理请求时可能...

    apache-tomcat-7.0.40-src

    Apache Tomcat 7.0.40 是一个广泛使用的开源软件,它是一个实现了Java Servlet、JavaServer Pages(JSP)和Java EE的Web应用程序容器。...对于Java Web开发人员来说,深入学习和理解Tomcat源码是提升技能的重要步骤。

    tomcat-connectors-1.2.40-src.zip

    五、源码学习价值 1. 性能优化:通过阅读源码,我们可以了解请求处理流程中的瓶颈,优化线程池、缓冲区大小等参数,提升系统性能。 2. 扩展功能:根据需求,可以对现有协议进行扩展,如支持新的网络协议,或实现更...

    apache-tomcat-8.5.38-src.zip

    通过源码,开发者可以了解性能瓶颈并进行优化,比如调整线程池大小、内存分配等。 **7. 集成与集群** Tomcat可以与其他应用服务器(如Jetty、JBoss)集成,也可以配置为集群环境,提供高可用性和负载均衡。 **8. ...

    apache-tomcat-6.0.20-src

    - **线程池管理**:Tomcat如何优化并发性能,使用线程池来处理请求。 此外,源码还提供了自定义和扩展Tomcat的可能性,例如创建新的连接器、容器或过滤器,以满足特定的性能需求或安全策略。开发者还可以通过修改...

    jakarta-tomcat-connectors-1.2.15-src.zip

    5. **学习Java NIO和多线程**:Tomcat的连接器使用了Java的非阻塞I/O(NIO)技术,通过阅读源码,可以加深对Java并发编程的理解。 总的来说,"jakarta-tomcat-connectors-1.2.15-src.zip"为开发者提供了一个宝贵的...

    apache-tomcat-9.0.8-src源码资源

    Tomcat使用Executor线程池来处理请求,相关代码在`org.apache.tomcat.util.thread`包下。 8. **WebSocket支持**: 自Tomcat 7起,它开始支持WebSocket协议,相关的处理逻辑在`org.apache.tomcat.websocket`包中。...

    tomcat-connectors-1.2.27-src.tar.gz

    《深入解析Tomcat Connectors:基于1.2.27源码分析》 Tomcat Connectors,也称为Coyote,是Apache Tomcat服务器的核心组件之一,它负责处理网络连接和HTTP协议。在深入理解Tomcat Connectors之前,我们需要先了解...

    apache-tomcat-8.5.46-src.zip

    Apache Tomcat是一个开源的软件应用服务器,主要用于运行Java Servlet...深入学习和理解Tomcat源码,有助于开发者更好地控制和优化应用程序的运行环境,解决可能出现的问题,以及开发出更高效、更安全的Java Web应用。

    tomcat-coyote-7.0.34-sources.jar.zip

    4. **Executor**:Coyote使用了Executor(执行器)模型来管理线程池,例如`org.apache.tomcat.util.threads.TaskQueue`和`org.apache.tomcat.util.threads.TaskThreadLocal`,它们负责任务的分配和线程上下文的维护...

    apache-tomcat-9.0.14-src源码

    对于初次接触Tomcat源码的开发者,可以从阅读`src/main/java`目录下的源码开始,重点关注`org.apache.catalina`包下的类,以及`org.apache.coyote`和`org.apache.jasper`等包。同时,`conf/server.xml`是配置整个...

    tomcat源码学习之环境搭建

    在深入探讨Tomcat源码学习之前,我们首先要理解Tomcat是什么。Tomcat是一款开源的、免费的Web服务器和Servlet容器,由Apache软件基金会维护。它实现了Java Servlet和JavaServer Pages(JSP)规范,是Java EE应用...

    tomcat8源码-eclipse工程

    7. **Eclipse集成**:在Eclipse中导入Tomcat源码,可以方便地进行调试、代码分析和自定义修改。这需要配置Tomcat插件,设置源代码路径,以及正确配置项目的构建路径。 8. **部署与调试**:在Eclipse中如何部署Web...

Global site tag (gtag.js) - Google Analytics