Java并发
tips:
System.gc -> 垃圾回收
软引用: java.lang.ref.SoftReference
SoftReference<byte[]> sr = new SoftReference<>(new byte(1024));
ThreadLocal
什么是ThreadLocal?
threadlocal是一个线程内部的存储类。ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
原理:
ThreadLocal底层是通过ThreadlocalMap实现, 每个Thread对象(注意不是Threadlocal对象)都存在ThreadlocalMap,key是当前ThreadLocal对象,value是当前线程的共享数据对象。
public class Thread implements Runnable {
//......
//与此线程有关的ThreadLocal值。由ThreadLocal类维护
ThreadLocal.ThreadLocalMap threadLocals = null;
//与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//......
}
set()
获取当前线程
获取当前线程内部的threadLocals变量【ThreadLocalMap类型】
当前线程内部的threadLocals变量不为空,则设置值;为空则new
ThreadLocal 内存泄露问题是怎么导致的?
ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。
这样一来,ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。
- ThreadLocal在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。
- 使用完 ThreadLocal方法后最好手动调用remove()方法
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
jvm知识 引用
- 强引用
只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收。 - 软引用
仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次发出垃圾回收,回收软引用对象。
可以配合引用队列来释放软引用自身 - 弱引用
仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象。
可以配合引用队列来释放弱引用自身 - 虚引用
必须配合引用队列使用。主要配合ByteBuffer使用。被引用对象回收时,会将虚引用入队,由 Reference Handler线程调用虚引用相关方法释放直接内存。 - 终结器引用
无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才能回收被引用对象。