多线程-ThreadLocal

一,ThreadLocal与Synchonized区别

ThreadLocal<T>其实是与线程绑定的一个变量。ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享

可以看下threadLocal.get()方法的源码

每个线程都会有根据当前线程对应的map,取值的时候yehu也会从这个副本中取,所以每个线程的threadLocal是相互隔离的

package com.qingwei.springboot.juc;

/**
 * Created by kongwc on 2020/3/19.
 */
public class ThreadLocalDemo {
    private static ThreadLocal<Integer> total = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue(){
            return 1;
        }
    };

    public static void startLocalThread(){
        Thread[] threads = new Thread[5];
        for(int i=0; i<threads.length; i++){
            threads[i] = new Thread(new MyThread(i));
        }
        for(int i=0; i<threads.length; i++){
            threads[i].start();
        }
    }
    static class MyThread implements Runnable{
        private Integer index;
        MyThread(Integer i){
            this.index = i;
        }
        @Override
        public void run() {
            index = index + total.get();
            total.set(index);
            System.out.println("当前的总数为:" + total.get() + "----当前线程名称:" + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        startLocalThread();
    }
}

二、ThreadLocalsh使用不当引起内存泄漏问题 

 

在ThreadLocal.get()方法源码中一直往下看会发现yo有个WeakReference,此处表示弱引用,java中的引用分为四种,按照引用强度不同,从强到弱依次为:强引用、软引用、弱引用和虚引用,如果是弱引用,每次垃圾回收的时候都会回收掉,

由于ThreadLocalMap是以弱引用的方式引用着ThreadLocal,换句话说,就是ThreadLocal是被ThreadLocalMap以弱引用的方式关联着,因此如果ThreadLocal没有被ThreadLocalMap以外的对象引用,则在下一次GC的时候,ThreadLocal实例就会被回收,那么此时ThreadLocalMap里的一组KV的K就是null了,因此在没有额外操作的情况下,此处的V便不会被外部访问到,而且只要Thread实例一直存在,Thread实例就强引用着ThreadLocalMap,因此ThreadLocalMap就不会被回收,那么这里K为null的V就一直占用着内存

 

三. ThreadLocal使用建议

通过前面几节的分析,我们基本弄清楚了ThreadLocal相关设计和内存模型,对于是否会发生内存泄露做了分析,下面总结下几点建议:

  • 当需要存储线程私有变量的时候,可以考虑使用ThreadLocal来实现
  • 当需要实现线程安全的变量时,可以考虑使用ThreadLocal来实现
  • 当需要减少线程资源竞争的时候,可以考虑使用ThreadLocal来实现
  • 注意Thread实例和ThreadLocal实例的生存周期,因为他们直接关联着存储数据的生命周期
  • 如果频繁的在线程中new ThreadLocal对象,在使用结束时,最好调用ThreadLocal.remove来释放其value的引用,避免在ThreadLocal被回收时value无法被访问却又占用着内存

 

 

 

 
 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

裂魂人1214

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值