2 u011385186 u011385186 于 2015.07.16 23:59 提问

tomcat4.1.40源码阅读HttpProcessor疑点求解? 200C

1.首先:org.apache.catalina.connector.http.HttpConnector作为守护线程启动之

前,创建一个了Stack(org.apache.catalina.connector.http.HttpProcessor)用来准备

处理Socket。
HttpConnector的Start()方法:

 public void start() throws LifecycleException {

        // Validate and update our current state
        if (started)
            throw new LifecycleException
                (sm.getString("httpConnector.alreadyStarted"));
        threadName = "HttpConnector[" + port + "]";
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Start our background thread
//--------------------启动HttpConnector run() begin----------------
        threadStart();//见下方run()方法
//--------------------启动HttpConnector run() end------------------
        // Create the specified minimum number of processors
        while (curProcessors < minProcessors) {
            if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
                break;
//------------------------创建线程池begin-------------------------
            HttpProcessor processor = newProcessor();//见下方
//------------------------创建线程池end------------------------------
            recycle(processor);
        }

    }

HttpConnector的run()方法

  public void run() {
        // Loop until we receive a shutdown command
        while (!stopped) {
       // Accept the next incoming connection from the server socket
            Socket socket = null;
            try {
                socket = serverSocket.accept();
                if (connectionTimeout > 0)
                    socket.setSoTimeout(connectionTimeout);
                socket.setTcpNoDelay(tcpNoDelay);
            } catch (AccessControlException ace) {
                log("socket accept security exception", ace);
                continue;
            } catch (IOException e) {
                try {
                    //If reopening fails, exit
                    synchronized (threadSync) {
                        if (started && !stopped)
                            log("accept error: ", e);
                        if (!stopped) {osing server socket");
                            serverSocket.close();
                            serverSocket = open();
                        }
                    }
                } catch (IOException ioe) {
                    log("socket reopen, io problem: ", ioe);
                    break;
                } catch (KeyStoreException kse) {
                    log("socket reopen, keystore problem: ", kse);
                    break;
                } catch (NoSuchAlgorithmException nsae) {
             log("socket reopen, keystore algorithm problem: ", nsae);
                    break;
                } catch (CertificateException ce) {
                    log("socket reopen, certificate problem: ", ce);
                    break;
                } catch (UnrecoverableKeyException uke) {
                    log("socket reopen, unrecoverable key: ", uke);
                    break;
                } catch (KeyManagementException kme) {
              log("socket reopen, key management problem: ", kme);
                    break;
                }

                continue;
            }
            // Hand this socket off to an appropriate processor
            HttpProcessor processor = createProcessor();
            if (processor == null) {
                try {
                    log(sm.getString("httpConnector.noProcessor"));
                    socket.close();
                } catch (IOException e) {
                    ;
                }
                continue;
            }
//触发条件启动org.apache.catalina.connector.http.HttpProcessor begin
            processor.assign(socket);//见下方assign方法
//触发条件启动org.apache.catalina.connector.http.HttpProcessor end
            // The processor will recycle itself when it finishes

        }

   // Notify the threadStop() method that we have shut ourselves down
        synchronized (threadSync) {
            threadSync.notifyAll();
        }

    }

newProcessor()方法:

 private HttpProcessor newProcessor() {

        //        if (debug >= 2)
        //            log("newProcessor: Creating new processor");
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                ((Lifecycle) processor).start();
            } catch (LifecycleException e) {
                log("newProcessor", e);
                return (null);
            }
        }
        created.addElement(processor);
        return (processor);

    }

HttpProcessor的assign(Socket socket)方法:

 synchronized void assign(Socket socket) {
//----------------问题所在地 begin-----------------
        // Wait for the Processor to get the previous Socket
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
//----------------问题所在地 end-----------------
        // Store the newly available Socket and notify our thread
        this.socket = socket;
        available = true;
        notifyAll();

        if ((debug >= 1) && (socket != null))
            log(" An incoming request is being assigned");

    }

2.问题:我理解:明明在run()方法中,每个socket请求都会对应从professor池子里面找一个新的HttpProcessor出来。此时该HttpProcessor既然已经在池子里就一定是available=false的。那么就不可能在assign方法中出现available=true的情况。如果真是这样那么这段代码不就没有意义了么?还是我的理解有问题?

在HttpProcessor中有可能出现available=true然后又在assign()方法中接收socket的情况吗?


源码贴不上来,有需要可以邮件发送该tomcat对应完整源码

4个回答

devmiao
devmiao   Ds   Rxr 2015.07.17 06:04

可能啊,当所有的socket都分配掉了,就需要等待。

u011385186
u011385186 你意思指所有的HttpProcessor被分配掉吗?在程序中如果HttpProcessor全部被分配掉了并且超出了最大线程数量就会直接返回异常的。如果不是这个意思,希望能解释一下,谢谢。
2 年多之前 回复
oyljerry
oyljerry   Ds   Rxr 2015.07.17 07:50

多线程同步等情况,通过availbale来控制当前函数是否进入等待还是进入分配。存储。

u011385186
u011385186 回复oyljerry: 恩,我也觉得可能是为了防止出现意外才添加上的。所以我特别关心如何出现的意外?
2 年多之前 回复
oyljerry
oyljerry 回复LCL_Ghoul: 是不是还可能防止函数多次重入时有问题
2 年多之前 回复
u011385186
u011385186 恩,首先:这里每次socket请求过来都会单独采用一个全新的HttpProcessor对象,然后再启动其线程。这么来看,线程与线程之间并没有共享的内容,所以也就谈不上什么冲突。所以线程之间的分配问题应该不用考虑。现在问题是既然已经在HttpConnector中保证了每次的socket请求都会启动一个新的线程,然后再调用该线程的assign()方法,那有如何可能出现available=true的情况。
2 年多之前 回复
CSDNXIAON
CSDNXIAON   2015.07.21 17:26

tomcat源码阅读-1
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!

u011385186
u011385186 小N,链接没有解决问题呢。
2 年多之前 回复
laj12347
laj12347   2016.03.14 11:48

说一下我的看法,我认为每一个socket都是有自己的 线程处理器,处理器是在处理完毕socket后释放自己,把自己放到处理器队列中的,应该不会出现多个socket同时占用一个 线程处理器,可能是有内部bug。
或者就是写代码的人, 同步线线程的习惯或者喜好,使的代码变成这样的。

Csdn user default icon
上传中...
上传图片
插入图片