电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

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

瀏覽:124日期:2023-02-19 16:52:57
springboot單例模式與線程安全問題踩的坑

最近有客戶反映,使用公司產品時,偶爾會存在崩潰情況,自己測試無問題,然后去查日志,是報空指針。

于是順藤摸瓜 往上找,好嘛,之前的開發使用了成員變量,感覺問題就是在這里了,因為眾所周知,springboot 采用的是單例模式,所以,使用成員變量時一定要謹慎。

下面上一張該類的截圖:

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

大家可能看到了,該類上面加上了@Scope('prototype') 注解,該注解的作用是將該類變成多例模式。講道理因為變為了多例,應該不會有線程問題了。

我先說下我這邊的一個代碼環境,上面大家看到的BaseController這個類里面有個init方法,會在繼承它的類的所有方法前執行。

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

使用的是@ModelAttribute注解,這個注解的意思是,在該controller的所有方法前執行,意在初始化,我猜測之前的同事應該是為了獲取相同的一些參數,抽調出來做一個父類,隨著迭代,別的同事為了方便,拿來就用,導致很多controller繼承了該類。

@Scope('prototype')注解:

大家設想一下,若父類加了@Scope('prototype')注解,子類controller并沒有加該注解,會怎樣呢?該注解是否還有意義?再比如,我在某service上加上@Scope('prototype')注解,但調用的controller沒有加@Scope('prototype')注解,那么會出現什么樣的結果呢?大家可以去測試一下,測試方法也很簡單,就是在對應的父類或service的無參構造方法里打印該類的地址。

下面說下我的測試結果:

先說父類上加了@Scope('prototype')注解,子類上沒有加這種情況。結果是,同一子類繼承的為同一父類,不同子類繼承為不同父類。理解一下,很簡單,因為springboot為單例模式,所以子類為單例,那么只有一個子類,父類肯定是一樣的。所以,不同線程過來使用的為同一變量,就會有問題。

同理:

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

現在說下解決方法:

1、是在繼承該controller的子類上都加上@Scope('prototype')注解。這樣做的好處是簡單。壞處也同樣明顯,因為是多例的,那么就會產生大量的實體類,占用大量內存,若是回收不及時,有可能會出現內存溢出。

2、是將變量私有化,比如使用線程變量,對變量加鎖等,技術上會復雜一些,而且調試不太好調試。說不定那些地方就會出現問題,畢竟是老代碼。

3、將該類轉換為攔截器,將變量放入request里,用的時候取出來。

SpringMVC 或 SpringBoot 默認是單例模式(Singleton)多個請求是訪問的同一個方法,是如何實現線程安全的?

SpringMVC Controller默認情況下是Singleton(單例)的,當request過來,不用每次創建Controller,會用原來的instance去處理。那么當多個線程調用它的時候,會不會發生線程不安全呢?

1、先說明下 Controller默認情況 單例的問題:

使用Spring MVC有一段時間了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是因為線程安全問題,對于Spring MVC中bean默認都是(singleton)單例的,那么用@Controller注解標簽注入的Controller類是單例實現的?

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

以下是測試步驟,代碼與結果.

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

以下是測試代碼:

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;@Controllerpublic 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); }}

分別三次請求: http://localhost:8080/example/test.do?data=15

得到的返回結果如下。

第一次: singletonInt=15

第二次: singletonInt=30

第三次: singletonInt=45

從以上結果可以得知,singletonInt的狀態是共享的,因此Controller是單例的。

2、對別Struts與springmvc對比

Struts2:默認prototype,Struts2 是基于類的,處于線程安全的考慮,采用了prototype模式,也就是說每次請求都會新建一個類來處理,自然就沒有線程安全問題了,每次請求的類和數據都是單獨的。

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

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

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
主站蜘蛛池模板: 蜘蛛车-高空作业平台-升降机-高空作业车租赁-臂式伸缩臂叉装车-登高车出租厂家 - 普雷斯特机械设备(北京)有限公司 | 新型游乐设备,360大摆锤游乐设备「诚信厂家」-山东方鑫游乐设备 新能源汽车电池软连接,铜铝复合膜柔性连接,电力母排-容发智能科技(无锡)有限公司 | 金属波纹补偿器厂家_不锈钢膨胀节价格_非金属伸缩节定制-庆达补偿器 | 空调风机,低噪声离心式通风机,不锈钢防爆风机,前倾皮带传动风机,后倾空调风机-山东捷风风机有限公司 | 郑州律师咨询-郑州律师事务所_河南锦盾律师事务所 | 宝元数控系统|对刀仪厂家|东莞机器人控制系统|东莞安川伺服-【鑫天驰智能科技】 | 中央空调温控器_风机盘管温控器_智能_液晶_三速开关面板-中央空调温控器厂家 | 大流量卧式砂磨机_强力分散机_双行星双动力混合机_同心双轴搅拌机-莱州市龙跃化工机械有限公司 | 合肥废气治理设备_安徽除尘设备_工业废气处理设备厂家-盈凯环保 合肥防火门窗/隔断_合肥防火卷帘门厂家_安徽耐火窗_良万消防设备有限公司 | 防火门-专业生产甲级不锈钢钢质防火门厂家资质齐全-广东恒磊安防设备有限公司 | 杭州实验室尾气处理_实验台_实验室家具_杭州秋叶实验设备有限公司 | 碳化硅,氮化硅,冰晶石,绢云母,氟化铝,白刚玉,棕刚玉,石墨,铝粉,铁粉,金属硅粉,金属铝粉,氧化铝粉,硅微粉,蓝晶石,红柱石,莫来石,粉煤灰,三聚磷酸钠,六偏磷酸钠,硫酸镁-皓泉新材料 | 多米诺-多米诺世界纪录团队-多米诺世界-多米诺团队培训-多米诺公关活动-多米诺创意广告-多米诺大型表演-多米诺专业赛事 | 艾默生变频器,艾默生ct,变频器,ct驱动器,广州艾默生变频器,供水专用变频器,风机变频器,电梯变频器,艾默生变频器代理-广州市盟雄贸易有限公司官方网站-艾默生变频器应用解决方案服务商 | 知企服务-企业综合服务(ZiKeys.com)-品优低价、种类齐全、过程管理透明、速度快捷高效、放心服务,知企专家! | 全自动包衣机-无菌分装隔离器-浙江迦南科技股份有限公司 | 咖啡加盟-咖啡店加盟-咖啡西餐厅加盟-塞纳左岸咖啡西餐厅官网 | 骨灰存放架|骨灰盒寄存架|骨灰架厂家|智慧殡葬|公墓陵园管理系统|网上祭奠|告别厅智能化-厦门慈愿科技 | 绿萝净除甲醛|深圳除甲醛公司|测甲醛怎么收费|培训机构|电影院|办公室|车内|室内除甲醛案例|原理|方法|价格立马咨询 | 探伤仪,漆膜厚度测试仪,轮胎花纹深度尺厂家-淄博创宇电子 | 西安中国国际旅行社(西安国旅)| 暴风影音 | 防伪溯源|防窜货|微信二维码营销|兆信_行业内领先的防伪防窜货数字化营销解决方案供应商 | 北京银联移动POS机办理_收银POS机_智能pos机_刷卡机_收银系统_个人POS机-谷骐科技【官网】 | 合肥白癜风医院_合肥治疗白癜风医院_合肥看白癜风医院哪家好_合肥华研白癜风医院 | 彼得逊采泥器-定深式采泥器-电动土壤采样器-土壤样品风干机-常州索奥仪器制造有限公司 | 浙江宝泉阀门有限公司 | 杭州中策电线|中策电缆|中策电线|杭州中策电缆|杭州中策电缆永通集团有限公司 | 大通天成企业资质代办_承装修试电力设施许可证_增值电信业务经营许可证_无人机运营合格证_广播电视节目制作许可证 | 私人别墅家庭影院系统_家庭影院音响_家庭影院装修设计公司-邦牛影音 | 苏州同创电子有限公司 - 四探针测试仪源头厂家 | 科昊仪器超纯水机系统-可成气相液氮罐-美菱超低温冰箱-西安昊兴生物科技有限公司 | 集装箱标准养护室-集装箱移动式养护室-广州璟业试验仪器有限公司 | 中红外QCL激光器-其他连续-半导体连续激光器-筱晓光子 | 论文查重_免费论文查重_知网学术不端论文查重检测系统入口_论文查重软件 | 胶原检测试剂盒,弹性蛋白检测试剂盒,类克ELISA试剂盒,阿达木单抗ELISA试剂盒-北京群晓科苑生物技术有限公司 | 空调风机,低噪声离心式通风机,不锈钢防爆风机,前倾皮带传动风机,后倾空调风机-山东捷风风机有限公司 | 企业彩铃制作_移动、联通、电信集团彩铃上传开通_彩铃定制_商务彩铃管理平台-集团彩铃网 | 电动百叶窗,开窗器,电动遮阳百叶,电动开窗机生产厂家-徐州鑫友工控科技发展有限公司 | 维泰克Veertek-锂电池微短路检测_锂电池腐蚀检测_锂电池漏液检测 | 大型多片锯,圆木多片锯,方木多片锯,板材多片锯-祥富机械有限公司 |