-
ThreadLocal是多线程中对于解决线程安全的一个操作类,它会为每个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
-
ThreadLocal是多线程中对于解决线程安全的一个操作类,它会为每个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
-
一个经典的例子,使用JDBC操作数据库时,会将每一个线程的Connection放入各自的ThreadLocal中,从而保证每个线程都在各自的 Connection 上进行数据库的操作,避免A线程关闭了B线程的连接。
- ThreadLocal和Synchonized都用于解决多线程并发访问。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。Synchronized通过锁机制使得变量在同一时刻只能被一个线程访问,而ThreadLocal为每一个线程提供一个变量副本,使得每个线程都只能对自己线程内部数据进行维护,从而实现共享数据的线程隔离。
- 要想理解内存泄露的话,则必须先要理解Java对象中的四种引用类型:强引用、软引用、弱引用、虚引用。
- 强引用:最为普通的引用方式,表示一个对象处于有用且必须的状态,如果一个对象具有强引用,则GC并不会回收它。即便堆中内存不足了,宁可出现OOM,也不会对其进行回收
User user = new User();
- 软引用:表示一个对象处于有用且非必须状态,如果一个对象处于软引用,在内存空间足够的情况下,GC机制并不会回收它,而在内存空间不足时,则会在OOM异常出现之间对其进行回收。但值得注意的是,因为GC线程优先级较低,软引用并不会立即被回收。
User user = new User(); SoftReference softReference = new SoftReference(user);
- 弱引用:表示一个对象处于可能有用且非必须的状态。在GC线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收。同样的,因为GC线程优先级较低,所以弱引用也并不是会被立刻回收。
User user = new User(); WeakReference weakReference = new WeakReference(user);
- 虚引用:表示一个对象处于无用的状态。在任何时候都有可能被垃圾回收。虚引用的使用必须和引用队列Reference Queue联合使用
User user = new User(); ReferenceQueue referenceQueue = new ReferenceQueue(); PhantomReference phantomReference = new PhantomReference(user,queue);内存泄露原因分析
- 根据前面对于ThreadLocal的源码分析可知,每一个Thread维护一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference。其中key为使用弱引用的ThreadLocal实例,value为线程变量的副本。
static class Entry extends WeakReference> { Object value; Entry(ThreadLocal> k, Object v) { super(k); value = v; } }
-
那么为什么要把key定义为使用弱引用的ThreadLocal呢?假设将key定义为强引用,回收ThreadLocal时,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,最终导致Entry内存泄漏。
-
为了避免该问题,则将key定义为弱引用,但是当GC时,则会造成因为key是弱引用,因此会被回收掉,但是value是强引用,仍然会存在,最终造成value的内存泄露。
如要避免ThreadLocal内存泄露的出现,也非常的简单。对于ThreadLocal的使用,务必记得要在最后一步执行remove即可



