源码:

public class WorkerStack {

        protected Worker[] workers = null;
        protected int end = 0;       
        public WorkerStack(int size) {
            workers = new Worker[size];
        }  
        /** 
         * Put the object into the queue.
         * 
         * @param   object      the object to be appended to the queue (first element). 
         */
        public void push(Worker worker) {
            workers[end++] = worker;
        }     
        /**
         * Get the first object out of the queue. Return null if the queue
         * is empty. 
         */
        public Worker pop() {
            if (end > 0) {
                return workers[--end];
            }
            return null;
        }
        
        /**
         * Get the first object out of the queue, Return null if the queue
         * is empty.
         */
        public Worker peek() {
            return workers[end];
        }
        /**
         * Is the queue empty?
         */
        public boolean isEmpty() {
            return (end == 0);
        }
        /**
         * How many elements are there in this queue?
         */
        public int size() {
            return (end);
        }
    }
Tomcat线程池还是比较简单,这池是一个数组,按队列方式操作。关键是如何使用线程池,

 在AprEndpoint.class对线程池的管理有四个方法,令我感觉到奇怪是的没有初始化线程池

 (1)protected Worker createWorkerThread(),此方法返一个可用的workThread,从线程池返回,如果线程池已无workThread,如满足条件则重新NEW一个,而满足的条件有二,现有线程数小于最大的线程数或是最大线程数为负数,因此在设置Tomcat线程池时把最大线程数设置为负数就可以创建任意多的工作线程

 (2) protected Worker newWorkerThread(),此方返回新的workThread,并启动,即调用start()方法,线程嘛

 (3) protected Worker getWorkerThread()  ,返回一个可用的workThread,从功能上好像与createWorkerThread()重复,其实不然,因为createWorkerThread()有可能返回一个null,而此方法是确定能返回一个workThread

 (4)protected void recycleWorkerThread(Worker workerThread) ,回收工作线程

 

 Tomcat主要四个线程:

Acceptor:用于接浏览器的请求,serverSocket.accept();特别的是:连接socket是用tomcat native,Tomcat使用APR来提供超强的可伸缩性和性能,更好地集成本地服务器技术

Poller:与APR相关

Worker:工作线程,接收的socket就是交给工作线程处理

Sendfile:与APR相关

 

 还有一个很重要的类,工作线程,Worker.class

源码:

       public void run() {

            // Process requests until we receive a shutdown signal

            while (running) {

                // Wait for the next socket to be assigned

                long socket = await();

                if (socket == 0)

                    continue;

                // Process the request from this socket

                if ((status != null) && 

                 (handler.event(socket, status) == Handler.SocketState.CLOSED)) {

                    // Close socket and pool

                    Socket.destroy(socket);

                    socket = 0;

                } else if ((status == null) && ((options && !setSocketOptions(socket)) 

                        || handler.process(socket) == Handler.SocketState.CLOSED)) {

                    // Close socket and pool

                    Socket.destroy(socket);

                    socket = 0;

                }

                // Finish up this request

                recycleWorkerThread(this);

            }

        } 

 与《How Tomcat works》里的第四章讲的原理相同,都是从Acceptor线程接收socket,调用getWorkerThread() 方法得到工作线程,再调用工作线程的assign()方法,在《How Tomcat works》讲到await()与assign()并不是在同一个线程上,说起来也奇怪,在同一个类中竟然会在不同的线程中。令我不解的有几点:

 (1)每一次都调用notifyAll()方法,会不会太浪费了?

    notifyAll()的解释是唤醒在此对象监视器上等待的所有线程,synchronized 方法在this同步, 在此对象监视器只有两个线程,即工作线程与Acceptor线程。因此notifyAll()只是唤醒另一个线程,不会浪费。。。

 (2)当一个工作线程正在运行的时候,此工作线程对象已不是线程池中,它的assign()方法又怎么可能会被调用呢? 

 (3)handler是每一个工作线程共享的,这样执行下去不会出现多线程安全问题? 

 

 

posted on 2010-06-08 23:43  ALVINZ  阅读(983)  评论(0编辑  收藏  举报