同步就是你叫我去吃飯,我聽到了就和你去吃飯;如果沒有聽到,你就不停的叫,直到我告訴你聽到了,才一起去吃飯。
異步就是你叫我,然後自己去吃飯,我得到消息後可能立即走,也可能等到下班纔去吃飯。
所以,要我請你吃飯就用同步的方法,要請我吃飯就用異步的方法,這樣你可以省錢。
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和
單線程運行的結果是一樣的,而且其他的
變量的值也和預期的是一樣的,就是線程安全的。
或者說:一個類或者程序所提供的接口對於線程來說是
原子操作或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題。
若每個線程中對
全局變量、
靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮
線程同步,否則的話就可能影響線程安全。
比如一個 ArrayList 類,在添加一個元素的時候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在
單線程運行的情況下,如果 Size = 0,添加一個元素後,此元素在位置 0,而且 Size=1;
而如果是在
多線程情況下,比如有兩個線程,線程 A 先將元素存放在位置 0。但是此時 CPU 調度線程A暫停,線程 B 得到運行的機會。線程B也向此 ArrayList 添加元素,因爲此時 Size 仍然等於 0 (注意哦,我們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然後線程A和線程B都繼續運行,都增加
Size 的值。
那好,我們來看看 ArrayList 的情況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是“線程不安全”了。
Struts2對Struts1進行了巨大的改進。
主要表現在如下幾個方面:
在Action的實現方面
Struts1要求必須統一擴展自Action類,而Struts2中可以是一個普通的
POJO。
線程模型方面
Struts1的Action是單實例的,一個Action的實例處理所有的請求。Struts2的Action是一個請求對應一個實例(每次請求時都新new出一個對象),沒有
線程安全方面的問題。
Servlet依賴方面
Struts1的Action依賴於Servlet API,比如Action的execute方法的參數就包括request和response對象。這使程序難於測試。Struts2中的Action不再依賴於Servlet API,有利於測試,並且實現TDD。
Struts1中強制使用ActionForm對象封裝請求的參數。Struts2可以選擇使用POJO類來封裝請求的參數,或者直接使用Action的屬性。
表達式語言方面
Struts1中整合了EL,但是EL對集合和索引的支持不強,Struts2整合了
OGNL(Object Graph NavigationLanguage)。
綁定值到視圖技術
Struts1使用標準的
JSP,Struts2使用“ValueStack”技術。
類型轉換
Struts1中的ActionForm基本使用String類型的屬性。Struts2中使用OGNL進行轉換,可以更方便的使用。
Struts1中支持覆蓋validate方法或者使用Validator
框架。Struts2支持重寫validate方法或者使用
XWork的驗證框架。
Struts1支持每一個模塊對應一個請求處理,但是模塊中的所有Action必須共享相同的生命週期。Struts2支持通過攔截器
堆棧爲每一個Action創建不同的生命週期。