好久未用,来复习一下。
使用场景
- 多线程下,该变量在每个线程中都是不同的实例,该变量调用链很深,不想每一层的方法中都放一个形参。
比如一个demo:
object Test {
var name: ThreadLocal<String> = ThreadLocal()
fun work() {
//synchronized(this) {
PrintService.work()
//}
}
}
object PrintService {
fun work() {
(1..9).forEach {
PrintDao.work(it)
}
}
}
object PrintDao {
fun work(num: Int) = println("${Thread.currentThread()} name is ${Test.name.get()} print $num")
}
fun main() {
(1..9).forEach {
thread(name = "Thread$it") {
Test.name.set(Thread.currentThread().name)
Test.work()
Test.name.remove()
}
}
}
这里大可以在每个方法上加一个形参name,依赖注入,thread里实例化这个形参也可以。
那如果我们的调用链很深,如果在每个方法上都加这么一个参数,而使用的地方在最低部,那这种方式是不是不优美,上游给下游传了个参数,结果只是为了参数往更下游传递。
那我们如果也类似的把这个参数放在一个工厂或单例里,不用ThreadLocal的话可以吗?当然可以,我们甚至可以创建一个Map<Thread,Object>的映射,来完成线程间不同的实例获取,那ThreadLocal实际上就帮我们做了这个事情,且做的更好了。
Thread维护ThreadLocal -> 实例,采用ThreadLocalMap完成这个映射关系。
如果直接用ThreadLocal完成Thread -> 实例的映射,那么每次增删线程都需要对映射map进行修改,涉及多线程并发的修改就得加锁,而这个映射关系如果放到线程内部就不再需要加锁了,因为单个线程只维护自己的ThreadLocal ->实例的映射,自然不会与其他线程产生交集。
未完,有空再写