ThreadLocalMap 弱引用
时间: 2023-10-26 10:41:18 浏览: 83
ThreadLocalMap 使用弱引用来解决 ThreadLocal 变量的内存泄漏问题。ThreadLocalMap 中的 Entry 对象使用 WeakReference 来引用 ThreadLocal 对象,当 ThreadLocal 对象没有其他强引用时,Entry 对象就会被垃圾回收器回收掉,从而避免了内存泄漏。
当一个线程结束时,其持有的 ThreadLocalMap 中的所有 Entry 对象都会被垃圾回收,因为这些 Entry 对象只被 ThreadLocalMap 弱引用,而不是被线程强引用。这也就是为什么在使用 ThreadLocal 时,需要在每个线程结束时调用 remove() 方法,以便及时清理 ThreadLocalMap 中的 Entry 对象,防止内存泄漏。
相关问题
threadlocalmap弱引用
ThreadLocalMap中的Entry结构的Key使用了弱引用。使用弱引用的好处在于,当JVM触发垃圾回收并回收了弱引用后,ThreadLocal在下一次调用get()、set()、remove()方法时就可以删除那些ThreadLocalMap中Key为null的值,从而释放内存,避免了内存泄漏的问题。这种设计可以让ThreadLocal的生命周期与Thread的生命周期解绑,使得ThreadLocalMap中的数据可以被及时清理。因此,使用弱引用可以起到惰性删除释放内存的作用,并且是ThreadLocal设计中的一个亮点。
ThreadLocalMap 弱引用 源码
ThreadLocalMap 是 ThreadLocal 类中的一个内部类,用于存储每个线程的 ThreadLocal 变量。在实现上,它是一个 hash 表,key 为 ThreadLocal 对象,value 为对应线程的变量值。
ThreadLocalMap 使用 Entry 内部类来表示每个键值对,Entry 继承自弱引用 WeakReference,这意味着当 ThreadLocal 对象被回收时,其在 ThreadLocalMap 中对应的键值对也会被自动删除,从而避免内存泄漏。
以下是 ThreadLocalMap 的部分源码:
```java
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
private Entry[] table;
/**
* The number of entries in the table.
*/
private int size = 0;
/**
* The next size value at which to resize (capacity * load factor).
*/
private int threshold;
/**
* The load factor for the hash table.
*/
private static final double LOAD_FACTOR = 0.75;
/**
* Set the value associated with key.
*/
private void set(ThreadLocal<?> key, Object value) {
// ...
}
/**
* Remove the entry for key.
*/
private void remove(ThreadLocal<?> key) {
// ...
}
/**
* Get the value for key.
*/
private Object get(ThreadLocal<?> key) {
// ...
}
```
在 set、remove 和 get 方法中,ThreadLocalMap 会先通过 Thread.currentThread() 获取当前线程,然后通过 ThreadLocal 的 hashCode() 方法计算出在 hash 表中对应的位置。如果该位置为空,则新建一个 Entry 对象并存储;否则,直接修改或返回该位置上的值。
需要注意的是,在 set 和 remove 方法中,ThreadLocalMap 会通过 expungeStaleEntries() 方法清除已经被回收的键值对,这也是为了避免内存泄漏。
阅读全文