Java 完全理解强软弱虚和ThreadLocal

什么是强软弱虚?
强引用就是普通的new出来的对象,当没有引用再指向它时,它才会被GC回收,否则哪怕内存溢出也不会被GC回收,当然如果将引用重新赋值为null,则该引用对象就不再是强引用了

软引用是当将要发生内存溢出前,就会被GC回收,通常适合用来做网页或图片等资源的内存中的缓存,这样既使得图片这种占用内存比较多的资源可以更快的被回收,又降低了重新从磁盘或者网络加载这些资源的频率。

弱引用是每次GC都会被回收,ThreadLocal底层就是使用了弱引用

虚引用是在对象即将被回收前将其放入一个虚引用队列中,然后在队列中对这个对象做一些善后的操作,通常是帮助回收堆外内存,一般是java源码内部在使用
那么什么是堆外内存呢?
现在的jvm为了提高效率是有可能使用堆外内存的,比如网卡读数据的时候需要使用一个缓冲区,JVM如果不能直接访问缓冲区的数据,那么就需要把缓冲区的数据拷贝进堆内,这样就多了一次拷贝的操作,但NIO是允许一个引用直接指向堆外内存的,这样就省了一次数据拷贝,也叫ZERO COPY。

ThreadLocal的应用
spring里的事务就使用到了ThreadLocal
比如我们使用@Transactional注解来保证事务,在被该注解修饰的方法中查询了两次数据库的不同的表,假如这两次查询数据库是从数据库连接池中随机取的不同的connection,就不可能保证事务,但如果使用了@Transactional注解,则该方法内无论多少次连接数据库,都肯定使用的同一个connection,其原因是当我们启动事务时,spring则在线程本地ThreadLocal中放入一个connection,之后的数据库连接就直接从ThreadLocal中取connection,从而保证在一个事务中的数据库连接永远只会使用同一个connection。

场景一:解决静态工具类的线程安全问题
每个线程需要独享的对象,比如静态的工具类SimpleDateFormat和Random等

场景二:避免传递参数的麻烦
如果很多方法中都在传递相同的参数,则可以存入到ThreadLocal中

ThreadLocal的底层是怎么实现的?
任何一个线程都有一个成员变量,这个成员变量是一个key value数据结构的map,当使用ThreadLocal去set数据时,实际上是set到了当前线程的ThreadLocalMap中,key就是ThreadLocal对象本身,value就是set进去的值。当调用set方法时,ThreadLocal会生成一个Entry 键值结构的对象,该对象继承自弱引用WeakReference,Entry对象的构造方法中调用了super的构造方法并将key传入了父类构造方法中(也就是弱引用WeakReference的构造方法),最终的结构就是键是弱引用,值是强引用。之所以key是弱引用是为了更好的回收ThreadLocal对象,如果key(也就是ThreadLocal对象)是强引用,那么当线程结束后,ThreadLocalMap中的key也就是ThreadLocal对象还在,这样就会造成ThreadLocal对象在很难被回收的局面。故将其设计为弱引用,每次都会被GC回收掉。从而避免内存泄漏。
ThreadLocal的get方法则是获取当前线程的ThreadLocalMap,如果ThreadLocalMap是null则进行初始化new一个ThreadLocalMap并返回null,否则通过ThreadLocal对象本身去ThreadLocalMap中取值,毕竟key就是ThreadLocal对象嘛。

ThreadLocal的key是弱引用还会有内存泄漏风险吗?
key是一个弱引用,但是value是一个强引用,这就导致了当GC时,map的key会被垃圾回收掉变成null,但是value因为是强引用就不会被回收,随着这种情况的增多,会有内存泄漏的风险
所以使用完ThreadLocal对象后,应当调用remove方法去删除对象,从而避免内心泄漏。

ThreadLocal绝对的线程安全吗?
如果说给ThreadLocal set一个静态的对象,那么还是会有线程安全问题,因为这个对象本身就是多线程共享的,所以绝对不应该在ThreadLocal中去放置静态对象

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值