zoukankan      html  css  js  c++  java
  • ThreadLocal为什么不使用Thread-value实现

    实现

    各个Thread对象保存一个ThreadLocalMap<ThreadLocal,value>,保存的是本Thread涉及的所有的ThreadLocal变量的本线程版本数据。

    一个app中可能多出用到不同的ThreadLocal,tl1被t1 t3使用,tl2被t1,t2,t4使用,所以t1的Map中保存了两个entry。

    为什么不是的Map<Thread,Value>的实现

    假如一个ThreadLocal对象是一个Thread-Value简单map,那么需要保证这个map本身并发安全。已经知道HashMap在扩容时会发生死循环。

    优点

    • 并发程度

    所以,现在是在实现时,真的把ThreadLocal代表的语义变量设置到了线程局部变——Thread对象的私有数据中。
    而如果使用Map<Thread,Value>实现,实际上还是使用共享的结构控制模拟出局部的效果。需要同步控制。

    • 内存泄露

    Entry是弱引用,所以当tl对象本身可以回收的时候,Entry不会阻止tl被回收。
    但是如果不正确remove就会导致内存泄露,这个不是ThreadLocal的缺点,但是是使用者需要注意的一个要点。

    当不remove的时候,真正的value是被强引用的,只要thread还runnable,那么Thread对象不会回收,其引用的Map也不会回收,map引用的Entry对象也不会回收,只不过Entry对key的引用是弱引用,所以key可以回收,但是entry对value的应用是强引用,value会被阻止回收。——所以对于service性质的线程如果使用ThreadLocal而没有remove,那么就会一直保持泄露,虽然一个value不多,但是如果不断使用新的ThreadLocal对象,就会不断泄露。

    Tomcat的PermGen泄露。

    前提还是没有remove,因为Tomcat是使用线程池调用servlet,线程一直保持ThreadLocal对象的当前线程版本,忧郁真正的value可能是WebAppClassloader加载的class类型,那么value引用了Class对象,Class对象应用了WebAppClassloader对象,他们都不会被回收,那么webappclassloader对象加载的所有class文件在永久代占用的内存一直无法被回收。——一个webapp是一些class构成的,正常情况reload这个app的时候,如果webappClassloader对象不被引用就可以回收,那么就不会阻止方法区的空间回收。但是由于ThreadLocal导致的一个value对象的泄露导致一大片的方法区无法回收,reload几次的话就可能导致PermGen oom。

    tomcat webapp stop时应清理自己

    使用的ThreadLocal至少在webapp stop之前要remove。
    另外从tomcat的log中可以看出几点要点提示。
    SEVERE: The web application registered the JDBC driver [oracle.jdbc.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

    org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
    SEVERE: The web application appears to have started a thread named [Thread-10] but has failed to stop it. This is very likely to create a memory leak.

    and

    SEVERE: The web application created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@64b43712c]) and a v
    alue of type [org.apache.logging.log4j.core.async.AsyncLogger.Info] (value [org.apache.logging.log4j.core.async.AsyncLogger$Info@3404e643e]) but failed
    to remove it when the web application was stopped. This is very likely to create a memory leak.

    Read more: https://javarevisited.blogspot.com/2012/01/tomcat-javalangoutofmemoryerror-permgen.html#ixzz5kyBlAh6J

  • 相关阅读:
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    OA办公系统 Springboot Activiti6 工作流 集成代码生成器 vue.js 前后分离 跨域
    java企业官网源码 自适应响应式 freemarker 静态引擎 SSM 框架
    java OA办公系统源码 Springboot Activiti工作流 vue.js 前后分离 集成代码生成器
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    java 视频播放 弹幕技术 视频弹幕 视频截图 springmvc mybatis SSM
    最后阶段总结
    第二阶段学习总结
    第一阶段学习总结
  • 原文地址:https://www.cnblogs.com/linlei2099/p/10509895.html
Copyright © 2011-2022 走看看