Servlet线程安全
概述?
在探討java線程安全前,讓我們先簡(jiǎn)要介紹一下Java語(yǔ)言。?
任何語(yǔ)言,如C++,C#,Java,它們都有相通之處,特別是語(yǔ)法,但如果有人問(wèn)你,Java語(yǔ)言的核心是什么?類庫(kù)?關(guān)鍵字?語(yǔ)法?似乎都不 是。Java語(yǔ)言的核心,也就是Sun始終不愿意開(kāi)源的東西:Java虛擬機(jī)的實(shí)現(xiàn)(不過(guò)sun公開(kāi)了其Java虛擬機(jī)規(guī)范),也就有了BEA的 JRockit,IBM的Jikes,Sun的Hotspot。?
Java的核心有兩點(diǎn),Java類加載(Java Class Loader)和Java內(nèi)存管理,它們具體體現(xiàn)在Java類庫(kù)的以下幾個(gè)類:?
java.lang.ClassLoader(java.lang.Class):我們調(diào)用的類,包括其接口和超類,import的類是怎么被Java虛擬機(jī)載入的?為什么static的字段在servlet容器里面可以一直生存下去(Spring容器中)??
java.lang.Thread(java.lang.ThreadLocal):垃圾回收是怎么進(jìn)行的(垃圾回收線程)?我們的程序是怎么退出的??
java.lang.refelect.Proxy(java.lang.refelect.Method):為什么Tomcat、 Tapestry、Webwork、Spring等容器和框架可以通過(guò)配置文件來(lái)調(diào)用我們寫(xiě)的類?Servlet規(guī)范、JSF規(guī)范、EJB規(guī)范、JDBC 規(guī)范究竟是怎么回事?為什么它們幾乎都是一些接口,而不是具體類??
Servlet線程安全?
在Java的server side開(kāi)發(fā)過(guò)程中,線程安全(Thread Safe)是一個(gè)尤為突出的問(wèn)題。因?yàn)槿萜?#xff0c;如Servlet、EJB等一般都是多線程運(yùn)行的。雖然在開(kāi)發(fā)過(guò)程中,我們一般不考慮這些問(wèn)題,但診斷問(wèn)題 (Robust),程序優(yōu)化(Performance),我們必須深入它們。?
什么是線程安全??
在Java里,線程安全一般體現(xiàn)在兩個(gè)方面:?
1、多個(gè)thread對(duì)同一個(gè)java實(shí)例的訪問(wèn)(read和modify)不會(huì)相互干擾,它主要體現(xiàn)在關(guān)鍵字synchronized。如 ArrayList和Vector,HashMap和Hashtable(后者每個(gè)方法前都有synchronized關(guān)鍵字)。如果你在 interator一個(gè)List對(duì)象時(shí),其它線程remove一個(gè)element,問(wèn)題就出現(xiàn)了。?
2、每個(gè)線程都有自己的字段,而不會(huì)在多個(gè)線程之間共享。它主要體現(xiàn)在java.lang.ThreadLocal類,而沒(méi)有Java關(guān)鍵字支持,如像static、transient那樣。?
一個(gè)普遍的疑問(wèn),我們的Servlet中能夠像JavaBean那樣declare instance或static字段嗎?如果不可以?會(huì)引發(fā)什么問(wèn)題??
答案是:不可以。下面以實(shí)例講解:?
首先,寫(xiě)一個(gè)普通的Servlet,里面有instance字段count:
web.xml? >>
<servlet><servlet-name>SimpleServlet</servlet-name><servlet-class>servlet.SimpleServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>SimpleServlet</servlet-name><url-pattern>/SimpleServlet</url-pattern> </servlet-mapping>?
?
SimpleServlet? >>
public class SimpleServlet extends HttpServlet {private int counter = 0; @Overrideprotected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.getWriter().println("<HTML><BODY>");response.getWriter().println(this + " ==> ");response.getWriter().println(Thread.currentThread() + ": <br>"); for(int c=0;c<10;c++){response.getWriter().println("Counter = " + counter + "");try {Thread.sleep(1000); counter++; } catch (Exception e) {e.printStackTrace();}}response.getWriter().println("</BODY></HTML>");}}?
test.html? >>
<html> <body> <table> <tr> <td><iframe src="SimpleServlet" name="servlet1" height="200%"> </iframe ></td> </tr> </table> </body> </html>?
test.html的內(nèi)容如上所示,打開(kāi)3個(gè)IE瀏覽器,同時(shí)在瀏覽器中輸入:
a: http://localhost:8080/ServletTest/SimpleServlet b: http://localhost:8080/ServletTest/SimpleServlet c: http://localhost:8080/ServletTest/SimpleServlet
? 測(cè)試結(jié)果如下:
?????????
? 我們會(huì)發(fā)現(xiàn)三點(diǎn):?
1、Servlet是一個(gè)單例對(duì)象(Singleton),因?yàn)槲覀兛吹蕉啻握?qǐng)求的this指針?biāo)写蛴〕鰜?lái)的hashCode值都相同。
2、servlet在不同的線程(線程池)中運(yùn)行,如http-8080-1,http-8080-2,http-8080-3 等輸出值可以明顯區(qū)分出不同的線程執(zhí)行了不同一段Servlet邏輯代碼。
3、count變量在不同的線程中共享,而且它的值被不同的線程修改,輸出時(shí)已經(jīng)不是順序輸出。也就是說(shuō),其他的線程會(huì)篡改當(dāng)前線程中實(shí)例變量的值,針對(duì)這些對(duì)象的訪問(wèn)不是線程安全的。
上面的結(jié)果,違反了線程安全的兩個(gè)方面。?
那么,我們?cè)鯓颖WC按照我們期望的結(jié)果運(yùn)行呢?首先,我想保證產(chǎn)生的count都是順序執(zhí)行的。?
我們將Servlet代碼重構(gòu)如下:
?
public class SimpleServlet extends HttpServlet {private int counter = 0; private String mutex = ""; @Overrideprotected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.getWriter().println("<HTML><BODY>");response.getWriter().println(this + " ==> ");response.getWriter().println(Thread.currentThread() + ": <br>"); synchronized (mutex){for(int c=0;c<10;c++){response.getWriter().println("Counter = " + counter + "<BR>");try {Thread.sleep(1000); counter++; } catch (Exception e) {e.printStackTrace();}}}response.getWriter().println("</BODY></HTML>");}}?
這符合要求,輸出都是按順序的,這正式synchronized的含義。
附帶說(shuō)一下,我現(xiàn)在synchronized的是一個(gè)字符串變量mutex,不是this對(duì)象,這主要是從performance和 Scalability考慮。Synchronized用在this對(duì)象上,會(huì)帶來(lái)嚴(yán)重的可伸縮性的問(wèn)題(Scalability),所有的并發(fā)請(qǐng)求都要排隊(duì)!
?
轉(zhuǎn)載:http://www.cnblogs.com/gw811/archive/2012/09/07/2675294.html
轉(zhuǎn)載于:https://www.cnblogs.com/go-skill/p/6078082.html
總結(jié)
以上是生活随笔為你收集整理的Servlet线程安全的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 18.虚拟机linux上网问题
- 下一篇: 舞钢市汽车学校?