亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

淺談Spring中單例Bean是線程安全的嗎

瀏覽:66日期:2023-08-09 16:03:14

Spring容器中的Bean是否線程安全,容器本身并沒有提供Bean的線程安全策略,因此可以說Spring容器中的Bean本身不具備線程安全的特性,但是具體還是要結(jié)合具體scope的Bean去研究。

Spring 的 bean 作用域(scope)類型

1、singleton:單例,默認作用域。

2、prototype:原型,每次創(chuàng)建一個新對象。

3、request:請求,每次Http請求創(chuàng)建一個新對象,適用于WebApplicationContext環(huán)境下。

4、session:會話,同一個會話共享一個實例,不同會話使用不用的實例。

5、global-session:全局會話,所有會話共享一個實例。

線程安全這個問題,要從單例與原型Bean分別進行說明。

原型Bean

對于原型Bean,每次創(chuàng)建一個新對象,也就是線程之間并不存在Bean共享,自然是不會有線程安全的問題。

單例Bean

對于單例Bean,所有線程都共享一個單例實例Bean,因此是存在資源的競爭。

如果單例Bean,是一個無狀態(tài)Bean,也就是線程中的操作不會對Bean的成員執(zhí)行查詢以外的操作,那么這個單例Bean是線程安全的。比如Spring mvc 的 Controller、Service、Dao等,這些Bean大多是無狀態(tài)的,只關(guān)注于方法本身。

有狀態(tài)對象(Stateful Bean) :就是有實例變量的對象,可以保存數(shù)據(jù),是非線程安全的。每個用戶有自己特有的一個實例,在用戶的生存期內(nèi),bean保持了用戶的信息,即“有狀態(tài)”;一旦用戶滅亡(調(diào)用結(jié)束或?qū)嵗Y(jié)束),bean的生命期也告結(jié)束。即每個用戶最初都會得到一個初始的bean。

無狀態(tài)對象(Stateless Bean):就是沒有實例變量的對象,不能保存數(shù)據(jù),是不變類,是線程安全的。bean一旦實例化就被加進會話池中,各個用戶都可以共用。即使用戶已經(jīng)消亡,bean 的生命期也不一定結(jié)束,它可能依然存在于會話池中,供其他用戶調(diào)用。由于沒有特定的用戶,那么也就不能保持某一用戶的狀態(tài),所以叫無狀態(tài)bean。但無狀態(tài)會話bean 并非沒有狀態(tài),如果它有自己的屬性(變量),那么這些變量就會受到所有調(diào)用它的用戶的影響,這是在實際應(yīng)用中必須注意的。

對于有狀態(tài)的bean,Spring官方提供的bean,一般提供了通過ThreadLocal去解決線程安全的方法,比如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等。

使用ThreadLocal的好處

使得多線程場景下,多個線程對這個單例Bean的成員變量并不存在資源的競爭,因為ThreadLocal為每個線程保存線程私有的數(shù)據(jù)。這是一種以空間換時間的方式。

當(dāng)然也可以通過加鎖的方法來解決線程安全,這種以時間換空間的場景在高并發(fā)場景下顯然是不實際的。

補充知識:Spring Bean Scope 有狀態(tài)的Bean 無狀態(tài)的Bean

在Spring的Bean配置中,存在這樣兩種情況:

<bean scope='singleton' />

<bean scope='prototype' />

當(dāng)然,scope的值不止這兩種,還包括了request,session 等。但用的最多的還是singleton單態(tài),prototype多態(tài)。

singleton表示該bean全局只有一個實例,Spring中bean的scope默認也是singleton.

prototype表示該bean在每次被注入的時候,都要重新創(chuàng)建一個實例,這種情況適用于有狀態(tài)的Bean.

對于SSH架構(gòu)的系統(tǒng),很少關(guān)心這方面,因為我們用到的一般都是singleton. Bean的注入由Spring管理。

對于有狀態(tài)的Bean呢?

下面是一個有狀態(tài)的Bean

package com.sw;public class TestManagerImpl implements TestManager{ private User user; public void deleteUser(User e) throws Exception { user = e ; //1 prepareData(e); } public void prepareData(User e) throws Exception { user = getUserByID(e.getId()); //2 ..... //使用user.getId(); //3 ..... ..... } }

如果該Bean配置為singleton,會出現(xiàn)什么樣的狀況呢?

如果有2個用戶訪問,都調(diào)用到了該Bean.

假定為user1,user2

當(dāng)user1 調(diào)用到程序中的1步驟的時候,該Bean的私有變量user被付值為user1

當(dāng)user1的程序走到2步驟的時候,該Bean的私有變量user被重新付值為user1_create

理想的狀況,當(dāng)user1走到3步驟的時候,私有變量user應(yīng)該為user1_create;

但如果在user1調(diào)用到3步驟之前,user2開始運行到了1步驟了,由于單態(tài)的資源共享,則私有變量user被修改為user2

這種情況下,user1的步驟3用到的user.getId()實際用到是user2的對象。

而如果是prototype的話,就不會出現(xiàn)資源共享的問題。

對于SSH來說,Bean的配置是沒錯的,配置為singleton ;實際應(yīng)該是這個例子不應(yīng)該用私有變量。這樣就使得這個Bean

由無狀態(tài)變成了有狀態(tài)Bean.還是應(yīng)該盡量使用無狀態(tài)Bean.如果在程序中出現(xiàn)私有變量,盡量替換為參數(shù)。對于每個訪問私有變量的方法增加變量傳入或者通過ThreadLocal來獲取也是不錯的方法。

真正出現(xiàn)上面代碼問題的也是少數(shù),出現(xiàn)的時候,一般是為了圖方便,一個很多方法都要用到的變量,如果都需要用參數(shù)的

方式傳遞多麻煩呀,這樣私有變量多好,不用參數(shù)那樣丑陋。但是丑陋并不代表不好,以對的,自己習(xí)慣的方式編程,才能

盡量避免問題的發(fā)生。

以上這篇淺談Spring中單例Bean是線程安全的嗎就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 成年美女毛片黄网站色奶头大全 | 国产特级毛片aaaaaaa高清 | 一级片一级毛片 | 外国一级黄色 | 深夜释放自己黄瓜视频 | 91视在线国内在线播放酒店 | 免费淫片 | 亚洲一区二区三区久久 | 在线观看日本免费视频大片 | 看黄色网址 | 国产精品二 | 欧美亚洲国产精品久久高清 | 成人日韩在线观看 | 在线视频不卡国产在线视频不卡 | 欧美vs日韩vs国产在线观看 | 久久亚洲国产最新网站 | 欧美激情一区二区 | 久草久操 | 尤物免费网站 | 国产黄大片在线视频 | 日韩欧美第一区二区三区 | 欧美日韩无 | 国产a级毛片 | 国产在线观看人成激情视频 | 国产日韩欧美在线一二三四 | 欧美日韩综合网在线观看 | 91免费小视频 | 国产五月色婷婷综合 | 深夜爽爽爽gif福利免费 | 久久国产大片 | 成人在线观看不卡 | 色综合亚洲综合网站综合色 | 九九在线精品视频xxx | 国产精品亚洲二区 | 亚洲精品一区二区三区在线看 | 国产美女啪啪 | 色图图片| 日韩免费高清视频网站 | 亚洲一区二区三区在线观看蜜桃 | 黄免费看 | 麻豆精品a在线观看 |