1. ThreadLocal
概述
ThreadLocal
是多线程中对于解决线程安全的一个操作类,它会为每个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal
同时实现了线程内的资源共享
案例:使用JDBC
操作数据库时,会将每一个线程的Connection
放入各自的ThreadLocal
中,从而保证每个线程都在各自的Connection
上进行数据库的操作,避免A
线程关闭了B
线程的连接。
2. ThreadLocal
基本使用
三个主要方法:
-
set(value)
设置值 -
get()
获取值 -
remove()
清除值
public class ThreadLocalTest {
static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
new Thread(() -> {
String name = Thread.currentThread().getName();
threadLocal.set("itcast");
print(name);
System.out.println(name + "-after remove : " + threadLocal.get());
}, "t1").start();
new Thread(() -> {
String name = Thread.currentThread().getName();
threadLocal.set("itheima");
print(name);
System.out.println(name + "-after remove : " + threadLocal.get());
}, "t2").start();
}
static void print(String str) {
//打印当前线程中本地内存中本地变量的值
System.out.println(str + " :" + threadLocal.get());
//清除本地内存中的本地变量
threadLocal.remove();
}
}
3. ThreadLocal
的实现原理&源码解析
ThreadLocal
本质来说就是一个线程内部存储类,从而让多个线程只操作自己内部的值,从而实现线程数据隔离
在ThreadLocal
中有一个内部类叫做ThreadLocalMap
,类似于HashMap
ThreadLocalMap
中有一个属性table数组,这个是真正存储数据的位置
set
方法
get
方法/remove
方法
4. ThreadLocal
内存泄露问题
Java
对象中的四种引用类型:强引用、软引用、弱引用、虚引用
- 强引用:最为普通的引用方式,表示一个对象处于有用且必须的状态,如果一个对象具有强引用,则
GC
并不会回收它。即便堆中内存不足了,宁可出现OOM
,也不会对其进行回收
- 弱引用:表示一个对象处于可能有用且非必须的状态。在
GC
线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收
每一个Thread
维护一个ThreadLocalMap
,在ThreadLocalMap
中的Entry
对象继承了WeakReference
。其中key
为使用弱引用的ThreadLocal
实例,value
为线程变量的副本
在使用ThreadLocal
的时候,强烈建议:务必手动remove
。