Java引用详解(强引用、软引用、弱引用、虚引用)
来源:互联网 发布:2016淘宝女装排行榜 编辑:程序博客网 时间:2024/05/19 23:01
Java引用详解(强引用、软引用、弱引用、虚引用)
ThreadLocal
每个线程都有一个独立于其他线程的上下文来保存这个变量,一个线程的本地变量对其他线程是不可见的。
2、独立于变量的初始化副本
ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。
3、状态与某一个线程相关联
ThreadLocal 不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的私有状态而引入的一个机制,理解这点对正确使用ThreadLocal至关重要。
ThreadLocal的接口方法
get()用来获取当前线程中变量的副本(保存在ThreadLocal中)。
set()用来设置当前线程中变量的副本。
remove()用来移除当前线程中变量的副本。
initialValue()是一个protected方法,用来给ThreadLocal变量提供初始值,每个线程都会获取这个初始值的一个副本。
使用示例
输出:CounterThread-[2] : 100
CounterThread-[0] : 100
CounterThread-[3] : 100
CounterThread-[1] : 100
CounterThread-[4] : 100
对initialValue函数的正确理解
输出:CounterThread-[0] : 12019
CounterThread-[2] : 14548
CounterThread-[1] : 13271
CounterThread-[3] : 34069
CounterThread-[4] : 34069
现在得到的计数不一样了,并且每次运行的结果也不一样,说好的线程本地变量呢?
如果我们想给每一个线程都保存一个Index对象应该怎么办呢?那就是创建对象的副本而不是对象引用的副本。
ThreadLocal源码分析
存储结构
ThreadLocal源码
内存泄露与WeakReference
对于键值对Entry,key为ThreadLocal实例,value为线程本地变量。不难发现,Entry继承自WeakReference<ThreadLocal>。WeakReference就是所谓的弱引用,也就是说Key是一个弱引用(引用ThreadLocal实例)。关于强引用、弱引用,参看:http://blog.csdn.net/sunxianghuang/article/details/52267282
输出:
Full GC 2
Full GC 1
My threadlocal 1 MB finalized.
Full GC 3
My 50 MB finalized.
Full GC 4
从输出可以看出,一旦threadLocal的强引用断开,key的内存就可以得到释放。只有当线程结束后,value的内存才释放。
每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap。Map中的key为一个threadlocal实例。这个Map的确使用了弱引用,不过弱引用只是针对key。每个key都弱引用指向threadlocal。当把threadlocal实例置为null以后,没有任何强引用指threadlocal实例,所以threadlocal将会被gc回收。但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用。
只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
注: 实线代表强引用,虚线代表弱引用.
所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露。但是value在threadLocal设为null和线程结束这段时间不会被回收,就发生了我们认为的“内存泄露”。
因此,最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的,就可能出现内存泄露。
为了最小化内存泄露的可能性和影响,在ThreadLocal的get,set的时候,遇到key为null的entry就会清除对应的value。
所以最怕的情况就是,threadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,这个线程结束,线程放回线程池中不销毁,这个线程一直不被使用,或者分配使用了又不再调用get,set方法,或者get,set方法调用时依然没有遇到key为null的entry,那么这个期间就会发生真正的内存泄露。
使用ThreadLocal需要注意,每次执行完毕后,要使用remove()方法来清空对象,否则 ThreadLocal 存放大对象后,可能会OMM。
为什么使用弱引用
To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys.
应用实例
Hibernate中使用Threadlocal实现线程相关的Session
参考:
JDK 1.7源码
http://my.oschina.NET/xpbug/blog/113444
- Java强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解
- Java-强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解
- java 强引用,软引用,弱引用,虚引用 详解
- Java引用详解(强引用、软引用、弱引用、虚引用)
- Java引用详解(强引用、软引用、弱引用、虚引用)
- 详解:强引用 软引用 弱引用 虚引用
- 强引用、软引用、弱引用、虚引用详解
- Java强引用、软引用、弱引用、虚引用详解 (转)
- Java强引用、软引用、弱引用、虚引用详解 (r)
- Java 强引用、 软引用、 弱引用、虚引用
- Java 强引用、 软引用、 弱引用、虚引用
- Java 强引用、 软引用、 弱引用、虚引用
- Java 强引用、 软引用、 弱引用、虚引用
- ES性能调优权威指南(篇一)
- hdu 1506 Largest Rectangle in a Histogram
- 打造逼真趣味DIY印章
- MATLAB Starting Error in Ubuntu 12.04: libc.so.6: not found
- 浏览器关闭后,Session就销毁了吗?
- Java引用详解(强引用、软引用、弱引用、虚引用)
- JS中setTimeout()的用法详解
- 第一次写博客
- iOS_Runtime3_动态添加方法
- radio,checkbox的重复点击实现
- Git 使用基础和示例
- 3398-数据结构实验之排序一:一趟快排
- Hibernate-增删改查
- java、python--差分隐私拉普拉斯分布(Laplace)实现