天天看點

關于tomcat中Servlet對象池

Servlet在不實作SingleThreadModel的情況下運作時是以單個執行個體模式,如下圖,這種情況下,Wrapper容器隻會通過反射執行個體化一個Servlet對象,對應此Servlet的所有用戶端請求都會共用此Servlet對象,而對于多個用戶端請求tomcat會使用多線程處理,是以應該保證此Servlet對象的線程安全,多個線程不管執行順序如何都能保證執行結果的正确性。例如剛做web應用開發時可能會犯的一個錯誤:在某個Servlet中使用成員變量累加去統計通路次數,這就存線上程安全問題。

關于tomcat中Servlet對象池

為了支援一個Servlet對象對應一個線程,Servlet規範提出了一個SingleThreadModel接口,tomcat容器必須要完成的機制是:如果某個Servlet類實作了SingleThreadModel接口則要保證一個線程獨占一個Servlet對象。假如線程1正在使用Servlet對象1,則線程2隻能用Servlet對象2。

針對SingleThreadModel模式,tomcat的Wrapper容器使用了對象池政策,Wrapper容器會有一個Servlet堆儲存若幹個該Servlet對象,當需要該Servlet對象時從堆中pop一個對象,而當用完後則push回堆中。Wrapper容器中最多可以有20個該Servlet對象,例如xxxServlet類的對象池,已經有20個線程占用了20個對象,那麼第21個線程執行時就會阻塞等待,直到對象池中有可用的對象才繼續執行。

整個流程如下圖所示,某個線程處理用戶端請求,它首先嘗試從Servlet對象池中擷取Servlet對象,此時如果對象池有可用對象則直接傳回一個對象,如果不夠使用則繼續執行個體化Servlet對象并push進對象池,但Servlet對象的總數量必須保證在20個以内,如果20個Servlet對象都被其他線程使用了,那麼就必須要等到其他線程用完放回後才能擷取,此時該線程會一直阻塞等待。從對象池中擷取到Servlet對象後則調用Servlet對象的service方法對用戶端請求進行處理,處理完後再将Servlet對象放回對象池中。

關于tomcat中Servlet對象池

本節介紹了Servlet對象池,它是為了支援Servlet規範SingleThreadModel接口而引入的,它就是一個棧結構,需要時就pop一個對象,使用完就push回去。

點選訂購作者《Tomcat核心設計剖析》

關于tomcat中Servlet對象池

繼續閱讀