其他分享
首页 > 其他分享> > ThreadLocal

ThreadLocal

作者:互联网


  问题描述,在工作中一次请求 请求接口一 ,将request保存到了ThreadLocal,调用接口二,而接口二也存入了ThreadLocal,接口二完成之后将ThreadLocal
 
 romove 了,在此回到接口一时数据已经没有了,导致了问题.
 
 然后就把接口二的 ThreadLocal.remove() 这行代码干掉了......
 
 ThreadLocal 是依存于 ThreadLocalMap 的 ,key 为 Thread.currentThread();
 
    static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
        
    在这里先说下对象的强弱软虚 容易记错的就是软和弱什么时候回收问题.

    1)软引用(Soft Reference):描述的是一些还有用但非必需的对象.在系统将会发生内存溢出之前,会把这些对象列入回收范围进行二次回收,也就是说系统将会发生内存溢出了,才会对他们进行回收.

    2)弱引用(Weak Reference):程度比软引用更弱一些.这些对象只能生存到下次 GC 之前.当 GC 工作时扫描到,无论内存是否足够都会将其回收.
    
    从这里我们可以发现 k 为弱引用.v为强引用.
    
    如果key被回收掉,则v可能发生内存泄露.
    
    static ThreadLocal threadLocal = new ThreadLocal();
    
    这种用法一个线程 一个线程永远只有一个KV对,并且不会被回收掉,只能是覆盖,跟随JVM启动而启动,结束而结束,可以remove删除掉自己设置的kv.
    
    另外一种用法
    class Test{
    ThreadLocal threadLocal = new ThreadLocal();
    }
    
    用对象持有 Test test = new Test();  test.threadLocal.set();
    
    如果对象使用完毕被回收(test=null; System.gc;),没有调用 threadLocal.remove();
    
    那这个 threadLocal 没有被回收,随着GC发生K被回收掉,这时候V就永远不会被回收,即使当前线程在此赋值,就会产生一条新纪录,导致内存堆积越来越多,OOM.
    
    JDK解决方案,当前线程 一定要在调用 get  set  remove  方法 会清理当前线程ThreadLocal空间内K为空的数据,赋值为NULL,帮助清理.
    
    自己解决就是一定要按规定调用remove.

    
   

标签:threadLocal,接口,ThreadLocal,线程,remove,回收
来源: https://www.cnblogs.com/li-xiaotian/p/16602114.html