在昨天的直播里面,有一个学生的简历上写,用户登录状态,最后放到了ThreadLocal里面。那就问他为什么要用ThreadLocal,它的作用是什么?但是回答的都不对。
这位同学让大拿老师想到了,大概三四年前,有一个顶级985的java实习生,过来实习了一周就跑了。这位同学走之前问了一个问题:“老师,实习项目里边,为什么用户的状态拦截也好,或者往service传的时候,不用ThreadLocal?我们学校的实验室项目都用的。”大拿老师当时就反问他一个问题:“那你觉得为什么要用?”
现在很多同学,因为大家在平时的工作里面,可能用不到一些要点。但是看了很多那种卖课的培训班,写了一些项目里面的要点,只说了这些要点如何如何地好,但是为什么好,为什么不好,在两种方案或三种方案可以选择的情况下,为什么选择这种而不是另一个,都不会去让你了解。但是这些问题才是真正做开发要去理解的问题。
包括这个直播里的孩子也是说:“如果用ThreadLocal的话,以后Controller 往service传值时,可以直接去传,而且不用写参数。”这个事本身它就没有什么逻辑。
首先,肯定是调service。如果想传一个登录状态,那无非就一个参数,就叫userID,搞那么多的其他的东西,就是在做无用功。所以就可以想到这么做的话会有三个问题。
第一个问题,现在的商用项目一般来说都是分层的,目的是为了解耦,可以去做复用。但是如果增加ThreadLocal,就会让它耦合性更强。因为两个层之间,是需要有一些参数在里面。那么以后去改代码的时候,就会很小心,防止这个事忘掉了,或者是没有去调用。
第二个事情,service层,也就是方法层。有可能service之间会彼此调用,在写别的service时,需要依赖一下service。service里面有ThreadLocal重复的值,但是调的时候又没有这个值,就冲突了,耦合性太强了。正常情况下,传个userid过去又简单,可读性又好。那为什么要多此一举呢?
第三个事情,就是更简单的一个问题。service层去写一个方法,可能很多别的团队会调用你的接口,那这个时候这个方法的参数和返回值,一般来说是不能用map的。如果用Map的话,很容易挨揍。
第四点,正规来说,登录时都会有个拦截器。是拦截用户过来token,然后用拦截器往Controller里面传参,还有是传址。这个时候可以用基于HTTP的threadLocal 去传,也可以基于HTTP的一个属性setAtrribue去传。有两种方案为什么要用更复杂,甚至可能会内存泄露的这种方案,而不是用更简单的三个值,然后那边去读一下就好了。
所以这里面这么多问题,为什么同学去用的时候,自己没有经过分析,反而别人说什么就是什么。如果说大家面试的时候,有准备过的话,知道threadLocal,它一般来说是解决线程并发问题的。但是大部分的移动互联网的基于spring boot的业务请求,都是没有并发问题的。
每个自己独立处理自己事情就好了,没有彼此关联,就没有并发的需求。那就不需要用一个非常复杂,而且还可能出现问题的一种方案,虽然看起来很高级,但是它要处理特殊场景,会对整个流程会造成影响的一种额外方案。
帖子还没人回复快来抢沙发