Tomcat源码分析【十五】请求处理过程分析之分配Servlet实例处理请求

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

文章首发于:clawhub.club


本篇内容源码在StandardWrapperValve的invoke方法中:

    //略......
    //分配一个servlet实例来处理这个请求
    servlet = wrapper.allocate();
    //略......

调用StandardWrapper中的方法:

    /**
         * Allocate an initialized instance of this Servlet that is ready to have
         * its <code>service()</code> method called.  If the servlet class does
         * not implement <code>SingleThreadModel</code>, the (only) initialized
         * instance may be returned immediately.  If the servlet class implements
         * <code>SingleThreadModel</code>, the Wrapper implementation must ensure
         * that this instance is not allocated again until it is deallocated by a
         * call to <code>deallocate()</code>.
         * 分配此Servlet的初始化实例,该实例已准备好调用其service()方法。
         * 如果servlet类没有实现SingleThreadModel,则可能立即返回(only)初始化的实例。
         * 如果servlet类实现了SingleThreadModel,
         * 包装器实现必须确保在调用deallocate()释放该实例之前不会再次分配该实例。
         *
         * @exception ServletException if the servlet init() method threw
         *  an exception
         * @exception ServletException if a loading error occurs
         */
        @Override
        public Servlet allocate() throws ServletException {
            //如果当前正在卸载此servlet,则抛出异常
            if (unloading) {
                throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
            }
            boolean newInstance = false;

            // If not SingleThreadedModel, return the same instance every time
            // 如果不是SingleThreadedModel,则每次返回相同的实例
            // singleThreadModel:这个servlet是否实现了SingleThreadModel接口?,这个接口已经被弃用了。
            // 也就是说实现了singleThreadModel接口,每次返回不同的Servlet
            if (!singleThreadModel) {
                // 如果需要,加载并初始化我们的实例
                if (instance == null || !instanceInitialized) {
                    synchronized (this) {
                        //如果没有实例的话,加载Servlet
                        if (instance == null) {
                            try {
                                if (log.isDebugEnabled()) {
                                    log.debug("Allocating non-STM instance");
                                }

                                // Note: We don't know if the Servlet implements
                                // SingleThreadModel until we have loaded it.
                                instance = loadServlet();
                                newInstance = true;
                                if (!singleThreadModel) {
                                    // For non-STM, increment here to prevent a race
                                    // condition with unload. Bug 43683, test case
                                    // #3
                                    countAllocated.incrementAndGet();
                                }
                            } catch (ServletException e) {
                                throw e;
                            } catch (Throwable e) {
                                ExceptionUtils.handleThrowable(e);
                                throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                            }
                        }
                        //如果没有初始化的话,初始化Servlet
                        if (!instanceInitialized) {
                            initServlet(instance);
                        }
                    }
                }

                if (singleThreadModel) {
                    if (newInstance) {
                        // Have to do this outside of the sync above to prevent a
                        // possible deadlock
                        synchronized (instancePool) {
                            instancePool.push(instance);
                            nInstances++;
                        }
                    }
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("  Returning non-STM instance");
                    }
                    // For new instances, count will have been incremented at the
                    // time of creation
                    if (!newInstance) {
                        countAllocated.incrementAndGet();
                    }
                    return instance;
                }
            }

            synchronized (instancePool) {
                while (countAllocated.get() >= nInstances) {
                    // Allocate a new instance if possible, or else wait
                    if (nInstances < maxInstances) {
                        try {
                            instancePool.push(loadServlet());
                            nInstances++;
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            ExceptionUtils.handleThrowable(e);
                            throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                        }
                    } else {
                        try {
                            instancePool.wait();
                        } catch (InterruptedException e) {
                            // Ignore
                        }
                    }
                }
                if (log.isTraceEnabled()) {
                    log.trace("  Returning allocated STM instance");
                }
                countAllocated.incrementAndGet();
                return instancePool.pop();
            }
        }

其中的loadServlet与initServlet上一篇文章分析过,这里就不看了。此方法最终返回一个Servlet实例。

鉴于这篇文章没啥东西,就一块把deallocate方法看一看:

     /**
         * Return this previously allocated servlet to the pool of available
         * instances.  If this servlet class does not implement SingleThreadModel,
         * no action is actually required.
         *
         * @param servlet The servlet to be returned
         *
         * @exception ServletException if a deallocation error occurs
         */
        @Override
        public void deallocate(Servlet servlet) throws ServletException {

            // If not SingleThreadModel, no action is required
            if (!singleThreadModel) {
                countAllocated.decrementAndGet();
                return;
            }

            // Unlock and free this instance
            //解锁并释放此实例
            synchronized (instancePool) {
                countAllocated.decrementAndGet();
                instancePool.push(servlet);
                instancePool.notify();
            }

        }

本篇结束,下一篇分析过滤器链相关代码。


来源:https://www.jianshu.com/u/9632919f32c3

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Tomcat源码分析【十五】请求处理过程分析之分配Servlet实例处理请求

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏