为什么Spring中的对象默认要设计成单例的

问题 :

为什么要设计成单例
单例的bean如何解决线程安全问题
对于第一点,可以理解为为了简化资源消耗,因为每有一个请求打到Controller层十,如果该Controller是原型,那么就会重新实例化一个对象,这样对于高并发的情况下消耗是相当大的,所以设计为单例,所有请求访问的都是同一个对象。

但是这样就会有一个缺点,那就是多线程的情况下如何解决线程安全问题,因为你都是访问的同一个controller对象啊,假如此时多个线程同时访问该controller的同一个方法(假设该方法对实例变量进行了操作),那不就有线程安全问题了吗?那你说可以在需要的方法上加上悲观锁不就好了,频繁的线程切换会消耗大量cpu时间,在高并发惜时如金的情况下显然不合适,所以可以采用以“空间”换“时间”的做法:

threadlocal

常见的有RequestContextHolder、TransactionSynchronizationManager等都是采用threadlocal,其中RequestContextHolder的作用是获取当前请求的上下文,比如request、session这些,在没有threadlocal的情况下,我们大概要写一个加了悲观锁的静态方法,方法内容是获取当前线程的request对象,然后当前线程作为key,request对象作为value存到一个全局map里面。

有了threadlocal之后,我只需将request对象set入当前线程thread的Threadlocal.threadlocalmap属性中,threadlocal实际上并没啥用,只是起到一个“钩子”的作用,存值的时候负责用set方法把request对象甩到当前线程的threadlocalmap的entry[]数组中,取值的时候负责将threadlocalmap的entry[]数组对应的值从当前线程中“钩”出来(是通过threadlocal来作为key从entry[]中存取值,所以叫钩子):
在这里插入图片描述
除上图中的方法还有其他封装threadlocal的方法,这里就不细谈了。

题外话

部分面试题springbean单例是线程安全的吗, 其实问题本身有歧义, springbean和线程安全没有关系, spring只是提供了一个容器用于管理实例, 单例还是原型区别只是整个过程是否使用同一实例, spring不能也无法预知你代码内容是否造成线程安全问题, 你需要做的是自行注意代码线程安全问题, 所以相对于面视的时候直接抛出这个问题, 还不如待面试者回答完单例或原型的基础概念后, 抛砖引玉地来一句: “既然单例模式全程只使用同一个实例, 那如果我代码中有操作成员变量地代码, 那如何在多个请求打到这个实例上的时候保证线程安全?”, 问题清晰明了, 又能凸显面试官职业水平

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值