java对象的引用类型?
- 强【Object o = new Object()】
- 软【softreference,一个对象只有弱引用的情况下,只有在内存不足的情况下,被引用的对象才会被回收】
- 弱【weakreference,一个对象只有弱引用的情况下,引用的对象只要垃圾回收执行,就会被回收,而不管是否内存不足】
- 虚【phantomReference,GC回收,虚引用的对象被回收,虚引用会被加入到ReferenceQueue中,通知应用程序对象的回收情况】
threadLocal?

- threadLocal对象的声明一般设置为静态属性,这种情况下threadLocal对象的强引用一直存在
threadLocal 内存泄漏的场景
- tl的强引用一直存在
- t与t1的线程一直存在
- t与t1不调用remove,key和value将会一直存在,这里其实最大的问题是使用完成后value一直存在
为什么若引用能够一定程度上解决若引用?
- threadlocal没有强引用 【线程结束时释放threadlocal的强引用/threadlocal对象对象在方法中创建且没有将它返回或者赋值给其他变量】
- t与t1的线程一直存在
- t与t1不调用remove,因为threadlocal只有若引用,就会被回收,这里其实解决的是key一直存在的问题
public class ThreadLocalSample {
public static void main(String[] args) throws InterruptedException {
ThreadLocalSample threadLocalSample = new ThreadLocalSample();
ArrayBlockingQueue<Runnable> runnables = new ArrayBlockingQueue<Runnable>(100);
int max=1,min = 1;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(min, max,1000, TimeUnit.SECONDS, runnables);
threadPoolExecutor.execute(threadLocalSample::useThreadLocal);
TimeUnit.SECONDS.sleep(5);
System.out.println("准备GC");
System.gc();
System.out.println("GC 完成");
threadPoolExecutor.execute(()->{
Thread thread = Thread.currentThread();
System.out.println("debug看看上面的线程threadLocalMap属性中是否有值");
});
TimeUnit.SECONDS.sleep(1000);
}
void useThreadLocal(){
ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
stringThreadLocal.set("aaaaa");
System.out.println("use threadLocal complete");
}
}
debug在#1处查看thread的threadLocalMap中的key 已经不存在了,即使我没有调用remove。个人认为实际上没有人会这么用threadLocal,这个若引用很鸡肋。
threadLocal的使用场景?
- 共享变量的多线程隔离场景【多线程下的方法参数多级传递,如果不想修改参数列表可以使用threadLocal】
- spring多数据源
- 日志追踪,MDC中traceId
如何解决thradLocal的泄漏?
- 尽量使用static final 修饰,禁止修改饮用
- 使用完成threadlocal之后,try finally 中调用remove
父子线程如何共享数据
- 使用InhertitableThreadlocal,Thread中保存了InhertitableThreadlocal的成员变量在init的方法中会cp父线程的设置的值,也就是说,只有创建新线程的那一刻进行复制
- 如果是线程池那依然获取不到,因为init方法在线程创建的时候执行过了
线程池中如何额共享数据
- 阿里巴巴的transmittable-thread-local.jar 中的transmittableThreadlocal