一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - 使用springboot單例模式與線程安全問題踩的坑

使用springboot單例模式與線程安全問題踩的坑

2021-11-04 10:50會(huì)飛的基德 Java教程

這篇文章主要介紹了使用springboot單例模式與線程安全問題踩的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

springboot單例模式線程安全問題踩的坑

最近有客戶反映,使用公司產(chǎn)品時(shí),偶爾會(huì)存在崩潰情況,自己測(cè)試無問題,然后去查日志,是報(bào)空指針。

于是順藤摸瓜 往上找,好嘛,之前的開發(fā)使用了成員變量,感覺問題就是在這里了,因?yàn)楸娝苤瑂pringboot 采用的是單例模式,所以,使用成員變量時(shí)一定要謹(jǐn)慎。

下面上一張?jiān)擃惖慕貓D:

使用springboot單例模式與線程安全問題踩的坑

大家可能看到了,該類上面加上了@Scope("prototype") 注解,該注解的作用是將該類變成多例模式。講道理因?yàn)樽優(yōu)榱硕嗬瑧?yīng)該不會(huì)有線程問題了。

我先說下我這邊的一個(gè)代碼環(huán)境,上面大家看到的BaseController這個(gè)類里面有個(gè)init方法,會(huì)在繼承它的類的所有方法前執(zhí)行。

使用springboot單例模式與線程安全問題踩的坑

使用的是@ModelAttribute注解,這個(gè)注解的意思是,在該controller的所有方法前執(zhí)行,意在初始化,我猜測(cè)之前的同事應(yīng)該是為了獲取相同的一些參數(shù),抽調(diào)出來做一個(gè)父類,隨著迭代,別的同事為了方便,拿來就用,導(dǎo)致很多controller繼承了該類。

@Scope("prototype")注解:

大家設(shè)想一下,若父類加了@Scope("prototype")注解,子類controller并沒有加該注解,會(huì)怎樣呢?該注解是否還有意義?再比如,我在某service上加上@Scope("prototype")注解,但調(diào)用的controller沒有加@Scope("prototype")注解,那么會(huì)出現(xiàn)什么樣的結(jié)果呢?大家可以去測(cè)試一下,測(cè)試方法也很簡(jiǎn)單,就是在對(duì)應(yīng)的父類或service的無參構(gòu)造方法里打印該類的地址。

下面說下我的測(cè)試結(jié)果:

先說父類上加了@Scope("prototype")注解,子類上沒有加這種情況。結(jié)果是,同一子類繼承的為同一父類,不同子類繼承為不同父類。理解一下,很簡(jiǎn)單,因?yàn)閟pringboot為單例模式,所以子類為單例,那么只有一個(gè)子類,父類肯定是一樣的。所以,不同線程過來使用的為同一變量,就會(huì)有問題。

同理:

在service上標(biāo)注@Scope("prototype")注解,那在同一個(gè)controller里,該service還是同一個(gè),也就是說還是單例的,在不同的controller里 是不同的。測(cè)試方法同上。

現(xiàn)在說下解決方法:

1、是在繼承該controller的子類上都加上@Scope("prototype")注解。這樣做的好處是簡(jiǎn)單。壞處也同樣明顯,因?yàn)槭嵌嗬模敲淳蜁?huì)產(chǎn)生大量的實(shí)體類,占用大量?jī)?nèi)存,若是回收不及時(shí),有可能會(huì)出現(xiàn)內(nèi)存溢出。

2、是將變量私有化,比如使用線程變量,對(duì)變量加鎖等,技術(shù)上會(huì)復(fù)雜一些,而且調(diào)試不太好調(diào)試。說不定那些地方就會(huì)出現(xiàn)問題,畢竟是老代碼。

3、將該類轉(zhuǎn)換為攔截器,將變量放入request里,用的時(shí)候取出來。

SpringMVC 或 SpringBoot 默認(rèn)是單例模式(Singleton)

多個(gè)請(qǐng)求是訪問的同一個(gè)方法,是如何實(shí)現(xiàn)線程安全的?

SpringMVC Controller默認(rèn)情況下是Singleton(單例)的,當(dāng)request過來,不用每次創(chuàng)建Controller,會(huì)用原來的instance去處理。那么當(dāng)多個(gè)線程調(diào)用它的時(shí)候,會(huì)不會(huì)發(fā)生線程不安全呢?

1、先說明下 Controller默認(rèn)情況 單例的問題:

使用Spring MVC有一段時(shí)間了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是因?yàn)榫€程安全問題,對(duì)于Spring MVC中bean默認(rèn)都是(singleton)單例的,那么用@Controller注解標(biāo)簽注入的Controller類是單例實(shí)現(xiàn)的?

測(cè)試結(jié)果發(fā)現(xiàn)spring3中的controller默認(rèn)是單例的,若是某個(gè)controller中有一個(gè)私有的變量i,所有請(qǐng)求到同一個(gè)controller時(shí),使用的i變量是共用的,即若是某個(gè)請(qǐng)求中修改了這個(gè)變量a,則,在別的請(qǐng)求中能夠讀到這個(gè)修改的內(nèi)容。 若是在@Controller之前增加@Scope(“prototype”),就可以改變單例模式為多例模式

以下是測(cè)試步驟,代碼與結(jié)果.

1. 如果是單例類型類的,那么在Controller類中的類變量應(yīng)該是共享的,如果不共享,就說明Controller類不是單例。

以下是測(cè)試代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ExampleAction {
    private int singletonInt=1;
     @RequestMapping(value = "/test")
     @ResponseBody
     public String singleton(HttpServletRequest request,
             HttpServletResponse response) throws Exception {
         String data=request.getParameter("data");
         if(data!=null&&data.length()>0){
             try{
              int paramInt= Integer.parseInt(data);
             singletonInt = singletonInt + paramInt;
             }
             catch(Exception ex){
                 singletonInt+=10;
             }
         }else{
             singletonInt+=1000;
         }
         return String.valueOf(singletonInt);
    }
}

分別三次請(qǐng)求: http://localhost:8080/example/test.do?data=15

得到的返回結(jié)果如下。

第一次: singletonInt=15

第二次: singletonInt=30

第三次: singletonInt=45

從以上結(jié)果可以得知,singletonInt的狀態(tài)是共享的,因此Controller是單例的。

2、對(duì)別Struts與springmvc對(duì)比

Struts2:默認(rèn)prototype,Struts2 是基于類的,處于線程安全的考慮,采用了prototype模式,也就是說每次請(qǐng)求都會(huì)新建一個(gè)類來處理,自然就沒有線程安全問題了,每次請(qǐng)求的類和數(shù)據(jù)都是單獨(dú)的。

Springmvc:默認(rèn)singleton 單例模式,Springmvc 是基于方法的,同一個(gè)url的請(qǐng)求是同一個(gè)實(shí)例處理的。每次請(qǐng)求都會(huì)把請(qǐng)求參數(shù)傳遞到同一個(gè)方法中,此時(shí)如果類里面有成員變量,那么這個(gè)變量就不是線程安全的了(例如上面的例子 private int singletonInt=1; 這個(gè)變量如果想線程安全則可以用ThreadLocal)。

在類中沒有成員變量的前提下則是線程安全的。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/weixin_38342534/article/details/86690166

延伸 · 閱讀

精彩推薦
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒有升過級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線程模擬多人同時(shí)搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程xml與Java對(duì)象的轉(zhuǎn)換詳解

    xml與Java對(duì)象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對(duì)象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程20個(gè)非常實(shí)用的Java程序代碼片段

    20個(gè)非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個(gè)非常實(shí)用的Java程序片段,對(duì)java開發(fā)項(xiàng)目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望...

    spcoder14552021-10-18
主站蜘蛛池模板: 男女污网站 | 久久久免费观看 | 啪啪国产视频 | 1769亚洲资源站365在线 | 亚洲精品久久久久福利网站 | 黑人巨大vs北条麻妃在线 | 四虎影音先锋 | 国产农村乱子伦精品视频 | 无限观看社区在线视频 | gayrb免费漫画入口 | 娇喘高潮教室h | xxxxxx日本处大片免费看 | 男男调教打屁股 | 操动漫美女视频 | 国语在线 | 国产精品国色综合久久 | 亚洲图片二区 | 国产rpg迷雾之风冷狐破解 | 久久re亚洲在线视频 | 私人黄色影院 | 日本中文字幕在线视频站 | 亚洲一区二区三区久久精品 | 秋霞黄色| 欧美国产日韩在线播放 | 国产高清在线视频一区二区三区 | bbbxxx乱大交欧美小说 | 成人免费福利网站在线看 | 国产乱码一卡二卡3卡四卡 国产乱插 | 爱情岛论坛亚洲品质自拍视频 | 天堂资源8中文最新版 | 国产精品区牛牛影院 | 青青草原国产一区二区 | 韩国久久| 日本无翼乌漫画 | 国产成人精品本亚洲 | 国产精品久久久久无毒 | 女人被爽到呻吟娇喘的视频动态图 | 日韩小视频在线观看 | 好吊色视频988gao在线观看 | 无限国产资源 | 欧美成人aletta ocean |