servlet 多執行緒

劍握在手發表於2013-11-29

servlet在伺服器中只有一個例項,那麼它響應請求的方式應該是多執行緒。

 

一,servlet容器如何同時處理多個請求

Servlet採用多執行緒來處理多個請求同時訪問,Servelet容器維護了一個執行緒池來服務請求。
執行緒池實際上是等待執行程式碼的一組執行緒叫做工作者執行緒(Worker Thread),Servlet容器使用一個排程執行緒來管理工作者執行緒(Dispatcher Thread)。

當容器收到一個訪問Servlet的請求,排程者執行緒從執行緒池中選出一個工作者執行緒,將請求傳遞給該執行緒,然後由該執行緒來執行Servlet的service方法。當這個執行緒正在執行的時候,容器收到另外一個請求,排程者執行緒將從池中選出另外一個工作者執行緒來服務新的請求,容器並不關心這個請求是否訪問的是同一個Servlet還是另外一個Servlet。當容器同時收到對同一Servlet的多個請求,那這個Servlet的service方法將在多執行緒中併發的執行。


       二,Servlet容器預設採用單例項多執行緒的方式來處理請求,這樣減少產生Servlet例項的開銷,提升了對請求的響應時間。對於Tomcat可以在server.xml中通過<Connector>元素設定執行緒池中執行緒的數目

就實現來說:
  排程者執行緒類所擔負的責任如其名字,該類的責任是排程執行緒,只需要利用自己的屬性完成自己的責任。所以該類是承擔了責任的,並且該類的責任又集中到唯一的單體物件中。而其他物件又依賴於該特定物件所承擔的責任,我們就需要得到該特定物件。那該類就是一個單例模式的實現了。

三,如何開發執行緒安全的Servlet   

                                                                                                            
        1,變數的執行緒安全:這裡的變數指欄位和共享資料(如表單引數值)。

  a,將 引數變數 本地化。多執行緒並不共享區域性變數.所以我們要儘可能的在servlet中使用區域性變數。
          例如:String user = "";
                     user = request.getParameter("user");

  b,使用同步塊Synchronized,防止可能非同步呼叫的程式碼塊。這意味著執行緒需要排隊處理。在使用同板塊的時候要儘可能的縮小同步程式碼的範圍,不要直接在sevice方法和響應方法上使用同步,這樣會嚴重影響效能。

 2,屬性的執行緒安全:ServletContext,HttpSession,ServletRequest物件中屬性
        ServletContext:(執行緒是不安全的)
        ServletContext是可以多執行緒同時讀/寫屬性的,執行緒是不安全的。要對屬性的讀寫進行同步處理或者進行深度Clone()。
        所以在Servlet上下文中儘可能少量儲存會被修改(寫)的資料,可以採取其他方式在多個Servlet中共享,比方我們可以使用單例模式來處理共享資料。
         HttpSession:(執行緒是不安全的)
         HttpSession物件在使用者會話期間存在,只能在處理屬於同一個Session的請求的執行緒中被訪問,因此Session物件的屬性訪問理論上是執行緒安全的。當使用者開啟多個同屬於一個程式的瀏覽器視窗,在這些視窗的訪問屬於同一個Session,會出現多次請求,需要多個工作執行緒來處理請求,可能造成同時多執行緒讀寫屬性。這時我們需要對屬性的讀寫進行同步處理:使用同步塊Synchronized和使用讀/寫器來解決。

  ServletRequest:(執行緒是安全的)
         對於每一個請求,由一個工作執行緒來執行,都會建立有一個新的ServletRequest物件,所以ServletRequest物件只能在一個執行緒中被訪問。ServletRequest是執行緒安全的。
         注意:ServletRequest物件在service方法的範圍內是有效的,不要試圖在service方法結束後仍然儲存請求物件的引用。

 3,使用同步的集合類:
       使用Vector代替ArrayList,使用Hashtable代替HashMap。

 4,不要在Servlet中建立自己的執行緒來完成某個功能。
       Servlet本身就是多執行緒的,在Servlet中再建立執行緒,將導致執行情況複雜化,出現多執行緒安全問題。

 5,在多個servlet中對外部物件(比方檔案)進行修改操作一定要加鎖,做到互斥的訪問。

四,SingleThreadModel介面
        javax.servlet.SingleThreadModel介面是一個標識介面,如果一個Servlet實現了這個介面,那Servlet容器將保證在一個時刻僅有一個執行緒可以在給定的servlet例項的service方法中執行。將其他所有請求進行排隊。伺服器可以使用多個例項來處理請求,代替單個例項的請求排隊帶來的效益問題。伺服器建立一個Servlet類的多個Servlet例項組成的例項池,對於每個請求分配Servlet例項進行響應處理,之後放回到例項池中等待下此請求。這樣就造成併發訪問的問題。此時,區域性變數(欄位)也是安全的,但對於全域性變數和共享資料是不安全的,需要進行同步處理。而對於這樣多例項的情況SingleThreadModel介面並不能解決併發訪問問題。

 

原文:http://blog.163.com/yxhui_cool/blog/static/770197702010101210342416/

相關文章