SpringBean默认是单例的,高并发情况下,如何保证并发安全?
1、知乎高赞:拼多多和国家电网,选哪个? 2、Windows 11 全网曝光,果然一股子苹果味... 3、小团队真的适合引入Spring Cloud微服务吗? 4、卷不动了?300 秒快速了解 Java 9 - 16 新特性,助你脱离内卷 5、Java 程序员常犯的 10 个 SQL 错误!
一、抛出问题
@Controller
public class HomeController {
private int i;
@GetMapping("testsingleton1")
@ResponseBody
public int test1() {
return ++i;
}
}
二、解决方案
2.1 单例变原型
@Scope("prototype")
或@Scope("request")
,对非web项目,在Component类上添加注解@Scope("prototype")
。2.2 线程隔离类ThreadLocal
@Controller
public class HomeController {
private ThreadLocal<Integer> i = new ThreadLocal<>();
@GetMapping("testsingleton1")
@ResponseBody
public int test1() {
if (i.get() == null) {
i.set(0);
}
i.set(i.get().intValue() + 1);
log.info("{} -> {}", Thread.currentThread().getName(), i.get());
return i.get().intValue();
}
}
[INFO ] 2019-12-03 11:49:08,226 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-1 -> 1
[INFO ] 2019-12-03 11:49:16,457 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-2 -> 1
[INFO ] 2019-12-03 11:49:17,858 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-3 -> 1
[INFO ] 2019-12-03 11:49:18,461 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-4 -> 1
[INFO ] 2019-12-03 11:49:18,974 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-5 -> 1
[INFO ] 2019-12-03 11:49:19,696 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-6 -> 1
[INFO ] 2019-12-03 11:49:22,138 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-7 -> 1
[INFO ] 2019-12-03 11:49:22,869 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-9 -> 1
[INFO ] 2019-12-03 11:49:23,617 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-8 -> 1
[INFO ] 2019-12-03 11:49:24,569 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-10 -> 1
[INFO ] 2019-12-03 11:49:25,218 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-1 -> 2
[INFO ] 2019-12-03 11:49:25,740 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-2 -> 2
[INFO ] 2019-12-03 11:49:43,308 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-3 -> 2
[INFO ] 2019-12-03 11:49:44,420 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-4 -> 2
[INFO ] 2019-12-03 11:49:45,271 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-5 -> 2
[INFO ] 2019-12-03 11:49:45,808 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-6 -> 2
[INFO ] 2019-12-03 11:49:46,272 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-7 -> 2
[INFO ] 2019-12-03 11:49:46,489 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-9 -> 2
[INFO ] 2019-12-03 11:49:46,660 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-8 -> 2
[INFO ] 2019-12-03 11:49:46,820 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-10 -> 2
[INFO ] 2019-12-03 11:49:46,990 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-1 -> 3
[INFO ] 2019-12-03 11:49:47,163 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-2 -> 3
......
总结:ThreadLocal的方式可以达到线程隔离,但还是无法达到并发安全。
2.3 尽量避免使用成员变量
@Controller
public class HomeController {
@GetMapping("testsingleton1")
@ResponseBody
public int test1() {
int i = 0;
// TODO biz code
return ++i;
}
}
2.4 使用并发安全的类
2.5 分布式或微服务的并发安全
三、补充说明
singleton
:单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;prototype
:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;
request
:搞web的大家都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不同就是创建后,接下来的管理,spring依然在监听;session
:每次会话,同上;global session
:全局的web域,类似于servlet中的application。
最近热文阅读:
1、知乎高赞:拼多多和国家电网,选哪个? 2、Windows 11 全网曝光,果然一股子苹果味... 3、小团队真的适合引入Spring Cloud微服务吗? 4、卷不动了?300 秒快速了解 Java 9 - 16 新特性,助你脱离内卷 5、Java 程序员常犯的 10 个 SQL 错误! 6、SpringBoot+webSocket实现扫码登录功能 7、短 URL 服务的设计以及实现 8、为什么阿里巴巴禁止使用存储过程? 9、面试官:说一下JDK/Dubbo/Spring 三种 SPI 机制,谁更好? 10、在外包干了三年,我废了..… 不吹不黑! 关注公众号,你想要的Java都在这里
评论