tomcat6容器中的Servlet的工作模式解析
Servlet的工作模式:HTTP请求交给Servlet容器时,依次触发Engine、Host、Context的管道,管道元素的invoke方法被调用。Servlet在tomcat中有两种工作方式,一种是单线程模型,即某一时刻一个Servlet实例的service方法只能被一个线程调用,这种模式下,tomcat会为每一servlet类创建一个实例池,有请求过来时都从该实例池中取一个实例来进行处
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实例放回实例池。
更多推荐
所有评论(0)