Spring - 單例Bean是如何保證性能的


1.Spring單例模式與線程安全

Spring框架里的bean或者component,在獲取實例時都是默認的單例模式。單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。

當多用戶同時請求一個服務時,容器會給每一個請求分配一個線程,並使用ThreadLocal,從而保證系統的性能。

ThreadLocal和線程同步機制相比有什么優勢呢?

在同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。 

而ThreadLocal則從另一個角度來解決多線程的並發訪問。ThreadLocal會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。 

概括起來說,對於多線程資源共享的問題,同步機制采用了“以時間換空間”的方式,而ThreadLocal采用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。 

2.Spring MVC Controller單例陷阱

單例模式下:

@RestController
@RequestMapping("controller")
public class TestController {
    private static int index_s = 0;//靜態的
    private int index = 0;//非靜態

    @GetMapping("/test")
    public String test() {
        return index_s++ + " | " + index++;
    }
}

結果:

0 | 0
1 | 1
2 | 2
3 | 3
4 | 4

多例模式下:

@RestController
@RequestMapping("controller")
@Scope("prototype")
public class TestController {
    private static int index_s = 0;//靜態的
    private int index = 0;//非靜態

    @GetMapping("/test")
    public String test() {
        return index_s++ + " | " + index++;
    }
}

結果:

0 | 0
1 | 0
2 | 0
3 | 0
4 | 0

由此可見:

單例是線程不安全的,會導致屬性的重復性利用。

1、不要在controller中定義成員變量。

2、萬一必須要定義一個非靜態成員變量時候,則通過注解@Scope("prototype"),將其設置為多例模式



參考資料:

https://blog.51cto.com/lavasoft/1394669

https://blog.csdn.net/paladinzh/article/details/88051356 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM