欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談springboot如何保證多線程安全

 更新時間:2021年12月29日 08:58:53   作者:李大爺們  
這篇文章主要介紹了springboot如何保證多線程安全,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

如何保證多線程安全

1.springboot在多線程并發(fā)訪問下是怎么做的

我們在Controller下,一般都是@AutoWired一些Service,由于這些Service都交給了spring進行管理,因此他們單例的,對于在Controller中調用他們的方法,由于方法在JVM中屬于棧操作,所以對于每一個線程來說,棧都是獨立的,因此是線程安全的。

而由于Controller本身是單例模式 (非線程安全的), 這意味著每個request過來,系統(tǒng)都會用原有的instance去處理,這樣導致了兩個結果:一是我們不用每次創(chuàng)建Controller,二是減少了對象創(chuàng)建和垃圾收集的時間;由于只有一個Controller的instance,當多個線程調用它的時候,它里面的instance變量就不是線程安全的了,會發(fā)生竄數(shù)據(jù)的問題。

如果我們定義了一個全局的實例,如 private Company company = new Company(); 而在@RequestMapping方法中去用到了他, 這里就存在并發(fā)線程安全的問題。

對于所有的請求request,這個company對象是相通的。

當然我們也可以用這個特性來制作訪問計數(shù)器 只需要定義一個private int cout = 0; 在每一次請求后cout++;

當然我并不推薦這么做,計數(shù)器最好用redis來操作。

總結以上問題,不要在Controller里出現(xiàn)類的實例。即便加了線程安全操作,也會出現(xiàn)性能問題。當然無論是Controller還是Service,如果你一定要使用對象的屬性,如private Company company = new Company();可以加上ThreadLocal的引用,如private ThreadLocal<Company> tc = new ThreadLocal<>();但是把這種使用的對象放進方法中初始化(即進入JVM棧中更好)。

2.controller在多線程下如何盡可能保證線程安全,如何取舍

當多個請求對controller進行請求時,它的instance的單例模式是線程不安全的,因此我們如果要保證完全的線程安全,需要對于每次請求都創(chuàng)建一個新的controller實例,在spring中使用@RequestScope注解定義它的作用域為requst,即一次請求即為一個實例,這樣就可以保證controller層面上的線程安全。但是這樣做會有一個很大的缺點,就是這種方式當并發(fā)很大時,創(chuàng)建bean的新實例就比重用原有的controller實例要慢許多。

因此還有折中的辦法,就是將@RequestScope設置為session級別的作用域,這樣每當一次會話,spring就會創(chuàng)建一個controller實例,而不需要每次請求都去創(chuàng)建一次實例,大大提高了訪問的速度,雖然這樣無法保證絕對的線程安全,但是在大部分的業(yè)務邏輯上都有效的防止了線程安全的問題。

此外,spring的作用域還有singleton(單例,也是spring默認的作用域級別,即永遠使用同一個實例)、prototype(原型)、globalSession(全局)

3.小結一下

Spring本身并沒有解決并發(fā)訪問的問題。如果bean的范圍不是線程安全的(例如在controller上面的成員變量或者靜態(tài)變量就是線程不安全的),但其方法包含一些您總是希望安全運行的關鍵代碼或者使用了靜態(tài)字段需要對其進行并發(fā)修改,請在該方法上使用synchronized關鍵字?;蛘呤褂靡恍┯刑峁┚€程安全的集合進行相應的多線程操作。

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

最近有客戶反映,使用公司產(chǎn)品時,偶爾會存在崩潰情況,自己測試無問題,然后去查日志,是報空指針。于是順藤摸瓜 往上找,好嘛,之前的開發(fā)使用了成員變量,感覺問題就是在這里了,因為眾所周知,springboot 采用的是單例模式,所以,使用成員變量時一定要謹慎。

下面上一張該類的截圖

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

我先說下我這邊的一個代碼環(huán)境

上面大家看到的BaseController這個類里面有個init方法,會在繼承它的類的所有方法前執(zhí)行。

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

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

下面說下我的測試結果

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

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

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

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

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

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

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java中Semaphore(信號量)的使用方法

    Java中Semaphore(信號量)的使用方法

    這篇文章主要介紹了Java中Semaphore(信號量)的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Java中Map集合的常用方法詳解

    Java中Map集合的常用方法詳解

    本篇文章給大家?guī)淼膬热菔顷P于Java中Map集合的常用方法詳解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。下面我們就來學習一下吧
    2021-11-11
  • Java與SpringBoot對redis的使用方式

    Java與SpringBoot對redis的使用方式

    這篇文章主要介紹了Java與SpringBoot對redis的使用方式,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • java 方法與數(shù)組基礎使用詳解

    java 方法與數(shù)組基礎使用詳解

    Java語言中的“方法”(Method)在其他語言當中也可能被稱為“函數(shù)”(Function),數(shù)組對于每一門編程語言來說都是重要的數(shù)據(jù)結構之一,當然不同語言對數(shù)組的實現(xiàn)及處理也不盡相同。Java 語言中提供的數(shù)組是用來存儲固定大小的同類型元素
    2022-04-04
  • 如何修改maven默認的JDK版本

    如何修改maven默認的JDK版本

    這篇文章主要介紹了如何修改maven默認的JDK版本,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 淺談用java實現(xiàn)事件驅動機制

    淺談用java實現(xiàn)事件驅動機制

    這篇文章主要介紹了淺談用java實現(xiàn)事件驅動機制,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Java多線程之同步鎖-lock詳解

    Java多線程之同步鎖-lock詳解

    這篇文章主要為大家詳細介紹了Java多線程中同步鎖-lock的原理與使用,文中的示例代碼講解詳細,對我們了解線程有一定幫助,需要的可以參考一下
    2022-10-10
  • 如何將char類型的數(shù)字字符轉換成int類型問題

    如何將char類型的數(shù)字字符轉換成int類型問題

    這篇文章主要介紹了如何將char類型的數(shù)字字符轉換成int類型問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot使用thymeleaf實現(xiàn)一個前端表格方法詳解

    SpringBoot使用thymeleaf實現(xiàn)一個前端表格方法詳解

    Thymeleaf是一個現(xiàn)代的服務器端 Java 模板引擎,適用于 Web 和獨立環(huán)境。Thymeleaf 的主要目標是為您的開發(fā)工作流程帶來優(yōu)雅的自然模板,本文就來用它實現(xiàn)一個前端表格,感興趣的可以了解一下
    2022-10-10
  • 使用IntelliJ IDEA 進行代碼對比的方法(兩種方法)

    使用IntelliJ IDEA 進行代碼對比的方法(兩種方法)

    這篇文章給大家?guī)砹藘煞NIntelliJ IDEA 進行代碼對比的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-01-01

最新評論