tomcat6容器中的Servlet的工作模式解析

5 篇文章 0 订阅

Servlet的工作模式:

HTTP请求交给Servlet容器时,依次触发Engine、Host、Context的管道,管道元素的invoke方法被调用。Servlet在tomcat中有两种工作方式,一种是单线程模型,即某一时刻一个Servlet实例的service方法只能被一个线程调用,这种模式下,tomcat会为每一servlet类创建一个实例池,有请求过来时都从该实例池中取一个实例来进行处理。另一种则是非线程模型,即有对某个servlet的请求过来时每次都使用该servlet的同一个实例来进行处理,就是相应的请求线程都使用同一个servlet进行处理,这种模型下会有线程并发执行的问题,在编写servlet的时候要加以注意。

下面以源代码进行分析:

Servlet主要是由StandardWrapper进行管理,请求交给StandardWrapperValve进行处理时,StandardWrapperValve在调用完过滤器链后,会请求StandardWrapper的allocate方法分配servlet并调用其service方法。处理完后会调用StandardWrapper的deallocate方法回收servlet。

1)     allocate方法

public Servlet allocate() throws ServletException {

        // If we are currently unloading this servlet, throw an exception
        if (unloading)
            throw new ServletException
              (sm.getString("standardWrapper.unloading", getName()));

        boolean newInstance = false;
        
        // If not SingleThreadedModel, return the same instance every time
        if (!singleThreadModel) {

            // Load and initialize our instance if necessary
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        try {
                            if (log.isDebugEnabled())
                                log.debug("Allocating non-STM instance");

                            instance = loadServlet();
                            // For non-STM, increment here to prevent a race
                            // condition with unload. Bug 43683, test case #3
                            if (!singleThreadModel) {
                                newInstance = true;
                                countAllocated.incrementAndGet();
                            }
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            throw new ServletException
                                (sm.getString("standardWrapper.allocate"), e);
                        }
                    }
                }
            }

            if (!singleThreadModel) {
                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) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        ;
                    }
                }
            }
            if (log.isTraceEnabled())
                log.trace("  Returning allocated STM instance");
            countAllocated.incrementAndGet();
            return (Servlet) instancePool.pop();

        }

    }

判断不是单线程模型,会看其servlet实例instance是否已经创建,没有创建则进行创建。如果已经创建了,将分配计数加1并返回该instance。是单线程模型则从实例池取servlet实例返回并将分配技术加1。Servlet实例的创建交由loadServlet方法来实施。

2)     deallocate方法

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();
        }

    }

首先会判断如果不是单线程模型,直接将使用的servlet的分配计数减1即可。如果是单线程模型则将分配计数减1,并把分配的servlet实例放回实例池。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值