Struts1和Struts2 action的線程安全。

去面試,問及struts方面的內容:aciton是否thread safe?

俺毫不猶豫的回答:不是

然後問,爲什麼不是?struts1和struts2那個是線程安全的?俺支吾了半天。也沒說個所以然出來。鬱悶。

下面是找的另一位同胞的文章:

action到底是thread safe還是unsafe呢 我們來看看servlet是否是thread safe ,action都是繼承至servlet的

看看其他資料的解釋:

JSP默認是以多線程方式執行的,這是JSP與ASP,PHP,PERL等腳本語言不一樣的地方,也是它的優勢之一,但如果不注意多線程中的同步問題,會使所寫的JSP程序有難以發現的錯誤。

JSP的中存在的多線程問題:

當客戶端第一次請求某一個JSP文件時,服務端把該JSP編譯成一個CLASS文件,並創建一個該類的實例,然後創建一個線程處理CLIENT端的請求。如果有多個客戶端同時請求該JSP文件,則服務端會創建多個線程。每個客戶端請求對應一個線程。以多線程方式執行可大大降低對系統的資源需求,提高系統的併發量及響應時間.對JSP中可能用的的變量說明如下:

實例變量
實例變量是在堆中分配的,並被屬於該實例的所有線程共享,所以不是線程安全的.
JSP系統提供的8個類變量
JSP中用到的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是線程安全的,APPLICATION在整個系統內被使用,所以不是線程安全的.
局部變量
局部變量在堆棧中分配,因爲每個線程都有它自己的堆棧空間,所以是線程安全的.
靜態類
靜態類不用被實例化,就可直接使用,也不是線程安全的.
外部資源:
在程序中可能會有多個線程或進程同時操作同一個資源(如:多個線程或進程同時對一個文件進行寫操作).此時也要注意同步問題.


使它以單線程方式執行,這時,仍然只有一個實例,所有客戶端的請求以串行方 式執行。這樣會降低系統的性能

最後的解決方案是:不要在action裏用實例變量。

又另一位同胞的文章,關於Struts2的線程安全:

在最近使用struts2的時候,都會看到別人寫的action中會加上一個scope("prototype")
這很是奇怪。爲什麼要加這個。。
在struts1中並不會加這個。。而且對於struts1中的action都是單例的。雖然聽說Singleton是個反模式,聽說有性能問題。但在使用struts1的時候沒有去深究,因爲大家都這麼用,用得很自然。

在查詢資料的時候又看到了很多沒有加上scope的問題
http://blog.csdn.net/foamflower/archive/2009/07/08/4329989.aspx
http://elf8848.javaeye.com/blog/356746
這些都是因爲沒有加上scope,導致上一次的變量值影響了下一次的請求。
還有如下問題:也讓我想不通。
引用
《strut2權威指南》中有這麼一段:
線程模式方面的對比:Struts1 Action是單例模式並且必須是線程安全的,因爲僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能做的事,並且要在開發時特別小心。Action資源必須是線程安全的或同步的;Struts 2 Action對象爲每一個請求產生一個實例,因此沒有線程安全問題 。

由於對設計模式不太瞭解,做了這麼之年Struts,一直不知道struts1是單例模式,不知這一點是從哪體現出來的?
而在開發過程中要怎樣注意“線程安全或同步”?struts2從哪體現的“沒有線程安全問題”?



那麼線程的問題到底體現在哪兒呢?

在查了些資料後。。明白了些!
http://hi.baidu.com/platon/blog/item/64a20ff3f96e7fce0b46e031.html
這文章中講了最基本的servlet的多線程問題。
其實servlet本身就是個多線程環境下的單例類。web容器就是這樣來處理servlet的。

通過這文章知道,爲什麼struts1中並沒有考慮到線程問題,因爲所有的代碼都是寫在execute的方法中,所有變量都是定義在裏面,所以沒有線程安全問題。

而現在的struts2就不一樣了。struts2的action中就像一個POJO一樣,定義了很多的類變量。這就有線程安全問題了。。此時,就使用scope=prototype來指定是個原型模式,而不是單例,這樣就解決了線程安全問題。每個線程都是一個新的實例。。

http://hi.baidu.com/niujunkai/blog/item/021964adc130660a4a36d6ab.html
這文章也說明了問題的關鍵之處。
引用
但是,線程同步是不得以的方法,是比較複雜的,而且會帶來性能的損失。等效的代碼中,不需要同步在編寫容易度和性能上會更好些。
我這裏強調的是什麼代碼是始終爲線程安全的、是不需要同步的。如下:
1)常量始終是線程安全的,因爲只存在讀操作。
2)對構造器的訪問(new 操作)是線程安全的,因爲每次都新建一個實例,不會訪問共享的資源。
3)最重要的是:局部變量是線程安全的。因爲每執行一個方法,都會在獨立的空間創建局部變量,它不是共享的資源。局部變量包括方法的參數變量。
struts user guide裏有:
Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class.
譯:只使用用局部變量。--編寫線程安全的代碼最重要的原則就是,在Action類中只使用局部變量,不使用實例變量。

還有此文
http://www.javaeye.com/topic/225749
 
發佈了70 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章