JUC-ThreadLocal

概念(就是将一个变量与线程绑定)

只记1:
ThreadLocal都是由private static修饰的
JUC-ThreadLocal_第1张图片

ThreadLocal与synchronized区别

JUC-ThreadLocal_第2张图片
ThreadLocal相对可以拥有更高的并发性

synchronized只提供一个变量(一个工具 => 一支笔 只提供一支笔就会产生哄抢,所以要使用synchronized进行排序)(想起多线程使用同一个SimpleDateFormat就会报错)。
而ThreadLocal为每个线程提供一个变量副本(多个工具 => 每人一支笔各用各的,互不干扰),副本与线程绑定,自己用自己的变量。

ThreadLocal使用场景

只记2:
1. 每个线程都有,但每个线程都不一样的变量
2. 该变量会在多个函数中使用
(就是为了避免传参的土操作)
JUC-ThreadLocal_第3张图片
JUC-ThreadLocal_第4张图片

思路

面临问题:转账过程ad.out和ad.in必须同时成功或者同时失败。

解决方法:ad.out/ad.in绑定在同一个事务中,若其中一个失败则进行事务回滚 => 则两个操作必须使用同一个数据库连接 => 则必须将dao中ad.out/ad.in两个方法的两个数据库连接变为同一个 => 将数据库连接提升到事务层(Service)=> 传递参数:在事务层(Service层)中就可以传参conn到ad.out/ad.in(dao层)中保证同一个线程共用一个conn。(传递参数会提高代码耦合(Service与dao))

传递参数问题:多个函数公共变量传递复杂,代码耦合性提升

解决办法: 使用ThreadLocal将conn变量与线程绑定
JUC-ThreadLocal_第5张图片
最后释放时需要remove掉线程的ThreadLocalMap中绑定的变量,防止内存泄漏。

线程与其ThreadLocal变量存储方式

JUC-ThreadLocal_第6张图片

ThreadLocal源码

public void set (T value)

JUC-ThreadLocal_第7张图片

public T get()

JUC-ThreadLocal_第8张图片

public void remove()

JUC-ThreadLocal_第9张图片

protected T initialValue()

需要修改初始值:则需要构造子类继承ThreadLocal类重写此方法
JUC-ThreadLocal_第10张图片

ThreadLocalMap

初始容量16,必须是2的整数幂
JUC-ThreadLocal_第11张图片
JUC-ThreadLocal_第12张图片

弱引用和内存泄漏

JUC-ThreadLocal_第13张图片

内存泄漏原因:
JUC-ThreadLocal_第14张图片

解决办法:
JUC-ThreadLocal_第15张图片

哈希解决:
ThreadLocalMap采用开放寻址法中的线性探测检测解决哈希冲突(会循环探测)
在清理过期Entery后如果长度大于等于原长度的2/3时会进行rehash,再次清理过期Entery后如果长度大于等于原长度的1/2时会进行扩容(过期Entry的意思就是ThreadLocal totalMap 该变量为空,里面没有内容了)

你可能感兴趣的:(java进阶,java,多线程)