国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Servlet單例多線程問題

2019-11-08 02:22:35
字體:
來源:轉載
供稿:網友

轉自:http://www.cnblogs.com/yjhrem/articles/3160864.html

復制代碼
             Servlet 單例多線程Servlet如何處理多個請求訪問?Servlet容器默認是采用單實例多線程的方式處理多個請求的:1.當web服務器啟動的時候(或客戶端發送請求到服務器時),Servlet就被加載并實例化(只存在一個Servlet實例);2.容器初始化化Servlet主要就是讀取配置文件(例如tomcat,可以通過servlet.xml的<Connector>設置線程池中線程數目,初始化線程池通過web.xml,初始化每個參數值等等。3.當請求到達時,Servlet容器通過調度線程(Dispatchaer Thread) 調度它管理下線程池中等待執行的線程(Worker Thread)給請求者;4.線程執行Servlet的service方法;5.請求結束,放回線程池,等待被調用;(注意:避免使用實例變量(成員變量),因為如果存在成員變量,可能發生多線程同時訪問該資源時,都來操作它,照成數據的不一致,因此產生線程安全問題)從上面可以看出:第一:Servlet單實例,減少了產生servlet的開銷;第二:通過線程池來響應多個請求,提高了請求的響應時間;第三:Servlet容器并不關心到達的Servlet請求訪問的是否是同一個Servlet還是另一個Servlet,直接分配給它一個新的線程;如果是同一個Servlet的多個請求,那么Servlet的service方法將在多線程中并發的執行;第四:每一個請求由ServletRequest對象來接受請求,由ServletResponse對象來響應該請求;Servlet/jsp技術和asp、php等相比,由于其多線程運行而具有很高的執行效率。由于Servlet/JSP默認是以多線程模式執行的,所以,在編寫代碼時需要非常細致地考慮多線程的安全性問題。 JSP的中存在的多線程問題: 當客戶端第一次請求某一個JSP文件時,服務端把該JSP編譯成一個CLASS文件,并創建一個該類的實例,然后創建一個線程處理CLIENT端的請求。如果有多個客戶端同時請求該JSP文件,則服務端會創建多個線程。每個客戶端請求對應一個線程。以多線程方式執行可大大降低對系統的資源需求,提高系統的并發量及響應時間. 對JSP中可能用的的變量說明如下: 實例變量: 實例變量是在堆中分配的,并被屬于該實例的所有線程共享,所以不是線程安全的. JSP系統提供的8個類變量 JSP中用到的OUT,REQUEST,RESPONSE,session,CONFIG,PAGE,PAGECONXT是線程安全的(因為每個線程對應的request,respone對象都是不一樣的,不存在共享問題), application在整個系統內被使用,所以不是線程安全的. 局部變量: 局部變量在堆棧中分配,因為每個線程都有它自己的堆??臻g,所以是線程安全的. 靜態類: 靜態類不用被實例化,就可直接使用,也不是線程安全的. 外部資源: 在程序中可能會有多個線程或進程同時操作同一個資源(如:多個線程或進程同時對一個文件進行寫操作).此時也要注意同步問題. 使它以單線程方式執行,這時,仍然只有一個實例,所有客戶端的請求以串行方式執行。這樣會降低系統的性能 問題 問題一. 說明其Servlet容器如何采用單實例多線程的方式來處理請求 問題二. 如何在開發中保證servlet是單實例多線程的方式來工作(也就是說如何開發線程安全的servelt)。 一. Servlet容器如何同時來處理多個請求 java的內存模型JMM(Java Memory Model) JMM主要是為了規定了線程和內存之間的一些關系。根據JMM的設計,系統存在一個主內存(Main Memory),Java中所有實例變量都儲存在主存中,對于所有線程都是共享的。每條線程都有自己的工作內存(Working Memory),工作內存由緩存和堆棧兩部分組成,緩存中保存的是主存中變量的拷貝,緩存可能并不總和主存同步,也就是緩存中變量的修改可能沒有立刻寫到主存中;堆棧中保存的是線程的局部變量,線程之間無法相互直接訪問堆棧中的變量。根據JMM,我們可以將論文中所討論的Servlet實例的內存模型抽象為圖所示的模型。 工作者線程Work Thread:執行代碼的一組線程。 調度線程Dispatcher Thread:每個線程都具有分配給它的線程優先級,線程是根據優先級調度執行的。 Servlet采用多線程來處理多個請求同時訪問。servlet依賴于一個線程池來服務請求。線程池實際上是一系列的工作者線程集合。Servlet使用一個調度線程來管理工作者線程。 當容器收到一個Servlet請求,調度線程從線程池中選出一個工作者線程,將請求傳遞給該工作者線程,然后由該線程來執行Servlet的service方法。當這個線程正在執行的時候,容器收到另外一個請求,調度線程同樣從線程池中選出另一個工作者線程來服務新的請求,容器并不關心這個請求是否訪問的是同一個Servlet.當容器同時收到對同一個Servlet的多個請求的時候,那么這個Servlet的service()方法將在多線程中并發執行。 Servlet容器默認采用單實例多線程的方式來處理請求,這樣減少產生Servlet實例的開銷,提升了對請求的響應時間,對于Tomcat可以在server.xml中通過<Connector>元素設置線程池中線程的數目。 就實現來說: 調度者線程類所擔負的責任如其名字,該類的責任是調度線程,只需要利用自己的屬性完成自己的責任。所以該類是承擔了責任的,并且該類的責任又集中到唯一的單體對象中。而其他對象又依賴于該特定對象所承擔的責任,我們就需要得到該特定對象。那該類就是一個單例模式的實現了。 注意:服務器可以使用多個實例來處理請求,代替單個實例的請求排隊帶來的效益問題。服務器創建一個Servlet類的多個Servlet實例組成的實例池,對于每個請求分配Servlet實例進行響應處理,之后放回到實例池中等待下此請求。這樣就造成并發訪問的問題。 此時,局部變量(字段)也是安全的,但對于全局變量和共享數據是不安全的,需要進行同步處理。而對于這樣多實例的情況SingleThreadModel接口并不能解決并發訪問問題。 SingleThreadModel接口在servlet規范中已經被廢棄了。二 如何開發線程安全的Servlet   1、實現 SingleThreadModel 接口   該接口指定了系統如何處理對同一個Servlet的調用。如果一個Servlet被這個接口指定,那么在這個Servlet中的service方法將不會有兩個線程被同時執行,當然也就不存在線程安全的問題。這種方法只要將前面的Concurrent Test類的類頭定義更改為: Public class Concurrent Test extends HttpServlet implements SingleThreadModel { ………… }   2、同步對共享數據的操作   使用synchronized 關鍵字能保證一次只有一個線程可以訪問被保護的區段,在本論文中的Servlet可以通過同步塊操作來保證線程的安全。同步后的代碼如下: ………… Public class Concurrent Test extends HttpServlet { ………… Username = request.getParameter ("username"); Synchronized (this){ Output = response.getWriter (); Try { Thread. Sleep (5000); } Catch (Interrupted Exception e){} output.數據庫,事務管理等服務接口交互,所以應用服務器的功能是很多的。常見的web服務器就是Tomcat,但Tomcat同樣也是Servlet服務器;常見的應用服務器有WebLogic,WebSphere,但都是收費的;沒有Servlet容器,可以用Web容器直接訪問靜態Html頁面,比如安裝了apache等;如果需要顯示Jsp/Servlet,就需要安裝一個Servlet容器;但是光有servlet容器也是不夠的,它需要被解析為html顯示,所以仍需要一個web容器;所以,我們常把web容器和Servlet容器視為一體,因為他們兩個容器都有對方的功能實現了,都沒有獨立的存在了,比如tomcat?。㏒ervlet是如何處理多個請求同時訪問呢?Servlet容器默認是采用單實例多線程的方式處理多個請求的:1.      當web服務器啟動的時候(或客戶端發送請求到服務器時),Servlet就被加載并實例化(只存在一個Servlet實例);2.      容器初始化Servlet。主要就是讀取配置文件(例如tomcat,可以通過servlet.xml的<Connector>設置線程池中線程數目,初始化線程池;通過web.xml,初始化每個參數值等等);3.      當請求到達時,Servlet容器通過調度線程(Dispatchaer Thread)調度它管理下的線程池中等待執行的線程(Worker Thread)給請求者;4.      線程執行Servlet的service方法;5.      請求結束,放回線程池,等到被調用;從上面可以看出:第一:Servlet單實例,減少了產生servlet的開銷;第二:通過線程池來響應多個請求,提高了請求的響應時間;第三:Servlet容器并不關心到達的Servlet請求訪問的是否是同一個Servlet還是另一個Servlet,直接分配給它一個新的線程;如果是同一個Servlet的多個請求,那么Servlet的service方法將在多線程中并發的執行;第四:每一個請求由ServletRequest對象來接受請求,由ServletResponse對象來響應該請求;問題出現了:同一個Servlet的的多個請求到來時,如果該Servlet中存在成員變量,可能發生多線程同時訪問該資源時,都來操作它,造成數據的不一致,因此產生線程安全問題。解決:1.      實現SingleThreadModel接口如果一個Servlet被這個接口指定,那么在這個Servlet中的service方法將不會有兩個線程被同時執行,當然也就不存在線程安全的問題;2.      同步對共享數據的操作使用synchronized關鍵字能保證一次只有一個線程可以訪問被保護的區段,Servlet可以通過同步塊操作來保證線程的安全。ServletRequest對象是線程安全的,但是ServletContext和HttpSession不是線程安全的;要使用同步的集合類:Vector代替ArrayList,HsahTable代替HashMap;3.      避免使用實例變量(成員變量)線程安全問題是由實例變量造成的,只要在Servlet里面的任何方法里面都不使用實例變量,那么該Servlet就是線程安全的。(所有建議不要在servlet中定義成員變量,盡量用局部變量代替)對上面的三種方法進行測試,可以表明用它們都能設計出線程安全的Servlet程序。但是,如果一個Servlet實現了SingleThreadModel接口,Servlet引擎將為每個新的請求創建一個單獨的Servlet實例,這將引起大量的系統開銷。SingleThreadModel在Servlet2.4中已不再提倡使用;同樣如果在程序中使用同步來保護要使用的共享的數據,也會使系統的性能大大下降。這是因為被同步的代碼塊在同一時刻只能有一個線程執行它,使得其同時處理客戶請求的吞吐量降低,而且很多客戶處于阻塞狀態。另外為保證主存內容和線程的工作內存中的數據的一致性,要頻繁地刷新緩存,這也會大大地影響系統的性能。所以在實際的開發中也應避免或最小化Servlet中的同步代碼;在Serlet中避免使用實例變量是保證Servlet線程安全的最佳選擇。從Java內存模型也可以知道,方法中的臨時變量是在棧上分配空間,而且每個線程都有自己私有的棧空間,所以它們不會影響線程的安全?!ervlet的線程安全問題只有在大量的并發訪問時才會顯現出來,并且很難發現,因此在編寫Servlet程序時要特別注意。線程安全問題主要是由實例變量造成的,因此在Servlet中應避免使用實例變量。如果應用程序設計無法避免使用實例變量,那么使用同步來保護要使用的實例變量,但為保證系統的最佳性能,應該同步可用性最小的代碼路徑。復制代碼
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大同县| 健康| 宝应县| 襄汾县| 巨野县| 长海县| 洪雅县| 西乌珠穆沁旗| 八宿县| 乌鲁木齐市| 自治县| 大石桥市| 宽甸| 宁城县| 襄垣县| 东源县| 郴州市| 海安县| 新平| 广元市| 抚松县| 温泉县| 安吉县| 昌宁县| 古交市| 南城县| 乐山市| 沁阳市| 浦北县| 岑溪市| 宝鸡市| 庆城县| 双鸭山市| 运城市| 林芝县| 青冈县| 彭山县| 射洪县| 阳谷县| 叙永县| 长寿区|