Spring 中的 bean 是線程安全的嗎?
singleton:單例,默認(rèn)作用域。
prototype:原型,每次創(chuàng)建一個新對象。
request:請求,每次Http請求創(chuàng)建一個新對象,適用于WebApplicationContext環(huán)境下。
session:會話,同一個會話共享一個實例,不同會話使用不用的實例。
global-session:全局會話,所有會話共享一個實例。
spring單例,為什么controller、service和dao確能保證線程安全?
有狀態(tài)就是有數(shù)據(jù)存儲功能
無狀態(tài)就是不會保存數(shù)據(jù) controller、service和dao層本身并不是線程安全的,只是如果只是調(diào)用里面的方法,而且多線程調(diào)用一個實例的方法,會在內(nèi)存中復(fù)制變量,這是自己的線程的工作內(nèi)存,是安全的。
Java虛擬機(jī)棧是線程私有的,它的生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。
局部變量的固有屬性之一就是封閉在執(zhí)行線程中。它們位于執(zhí)行線程的棧中,其他線程無法訪問這個棧。
首先問@Controller @Service是不是線程安全的?
@RestController
public?class?TestController?{
????private?int?var?= 0;
????
????@GetMapping(value?= "/test_var")
????public?String test() {
????????System.out.println("普通變量var:"?+ (++var));
????????return?"普通變量var:"?+ var?;
????}
}普通變量var:1
普通變量var:2
普通變量var:3@RestController
@Scope(value?= "prototype") // 加上@Scope注解,他有2個取值:單例-singleton 多實例-prototype
public?class?TestController?{
????private?int?var?= 0;
????
????@GetMapping(value?= "/test_var")
????public?String test() {
????????System.out.println("普通變量var:"?+ (++var));
????????return?"普通變量var:"?+ var?;
????}
}普通變量var:1
普通變量var:1
普通變量var:1@RestController
@Scope(value?= "prototype") // 加上@Scope注解,他有2個取值:單例-singleton 多實例-prototype
public?class?TestController?{
????private?int?var?= 0;
????private?static?int?staticVar = 0;
????@GetMapping(value?= "/test_var")
????public?String test() {
????????System.out.println("普通變量var:"?+ (++var)+ "---靜態(tài)變量staticVar:"?+ (++staticVar));
????????return?"普通變量var:"?+ var?+ "靜態(tài)變量staticVar:"?+ staticVar;
????}
}普通變量var:1---靜態(tài)變量staticVar:1
普通變量var:1---靜態(tài)變量staticVar:2
普通變量var:1---靜態(tài)變量staticVar:3@RestController
@Scope(value?= "singleton") // prototype singleton
public?class?TestController?{
????private?int?var?= 0; // 定義一個普通變量
????private?static?int?staticVar = 0; // 定義一個靜態(tài)變量
????@Value("${test-int}")
????private?int?testInt; // 從配置文件中讀取變量
????ThreadLocal tl = new?ThreadLocal<>(); // 用ThreadLocal來封裝變量
????@Autowired
????private?User user; // 注入一個對象來封裝變量
????@GetMapping(value?= "/test_var")
????public?String test() {
????????tl.set(1);
????????System.out.println("先取一下user對象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
????????user.setAge(1);
????????System.out.println("普通變量var:"?+ (++var) + "===靜態(tài)變量staticVar:"?+ (++staticVar) + "===配置變量testInt:"?+ (++testInt)
????????????????+ "===ThreadLocal變量tl:"?+ tl.get()+"===注入變量user:"?+ user.getAge());
????????return?"普通變量var:"?+ var?+ ",靜態(tài)變量staticVar:"?+ staticVar + ",配置讀取變量testInt:"?+ testInt + ",ThreadLocal變量tl:"
????????????????+ tl.get() + "注入變量user:"?+ user.getAge();
????}
} @Configuration
public?class?MyConfig?{
????@Bean
????public?User user(){
????????return?new?User();
????}
}先取一下user對象中的值:0===再取一下hashCode:241165852
普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:1===再取一下hashCode:241165852
普通變量var:2===靜態(tài)變量staticVar:2===配置變量testInt:2===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:1===再取一下hashCode:241165852
普通變量var:3===靜態(tài)變量staticVar:3===配置變量testInt:3===ThreadLocal變量tl:1===注入變量user:1先取一下user對象中的值:0===再取一下hashCode:853315860
普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:1===再取一下hashCode:853315860
普通變量var:1===靜態(tài)變量staticVar:2===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:1===再取一下hashCode:853315860
普通變量var:1===靜態(tài)變量staticVar:3===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1public?class?MyConfig?{
????@Bean
????@Scope(value = "prototype")
????public User user(){
????????return?new?User();
????}
}先取一下user對象中的值:0===再取一下hashCode:1612967699
普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:0===再取一下hashCode:985418837
普通變量var:1===靜態(tài)變量staticVar:2===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1
先取一下user對象中的值:0===再取一下hashCode:1958952789
普通變量var:1===靜態(tài)變量staticVar:3===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1???
作者:myseries
cnblogs.com/myseries/p/11729800.html
推薦閱讀
讀完《Effective Java》: 我整理這 50 條技巧
面試中又被問到Redis如何實現(xiàn)搶購,趕快代碼實現(xiàn)一波吧!
最后,推薦給大家一個有趣有料的公眾號:寫代碼的渣渣鵬,7年老程序員教你寫bug,回復(fù) 面試或資源 送一你整套開發(fā)筆記 有驚喜哦
評論
圖片
表情

