Java's ThreadLocals make certain things easy, but special care must be taken to make sure they are removed from threads when they are no longer needed. If ThreadLocals are not removed from threads, they can easily cause memory leaks, because threads can live much longer than the applications that are executed on a thread.

Consider a web application running inside a servlet container like Tomcat. Each request is handled by a thread from a thread pool. These threads can live well after you web app is undeployed from the server.

One of the easiest ways to get this wrong is to assume that ThreadLocal.get() returning null means that the ThreadLocal is not installed in the thread. This is not the case.

Each thread has a map of ThreadLocals, and when ThreadLocal.get() is called for the first time, it actually installs the ThreadLocalinto that ThreadLocal map for the current thread with the default value, which is usually null. You must still remove the ThreadLocal from the thread by calling ThreadLocal.remove().

As a rule of thumb, for ThreadLocals where the default value is null, if get() returns nullremove() should be called immediately.

I have written a class that does most of this for me:

/**
* A conservative {@link ThreadLocal} that removes itself from the thread
* whenever its value is {@code null}.
* @author Jesse Long
* @param <T> The type of the value stored in this {@link ThreadLocal}
*/
public abstract class ConservativeThreadLocal<T>
extends ThreadLocal<T>
{
/**
* Returns the current value of the variable, or {@code null} if it has not
* been set. This method takes care to remove this {@link ThreadLocal} from
* the thread if the value has not been set.
* @return the current value of the variable, or {@code null} if it has not
* been set.
*/
@Override
public final T get()
{
T t = super.get();
if (t == null){
remove();
}
return t;
} /**
* Returns {@code null}. This implementation always returns {@code null} so
* that this {@link ThreadLocal} implementation can use its absent on a
* thread as an indication that the value is not set.
* @return {@code null}
*/
@Override
protected final T initialValue()
{
return null;
} /**
* Returns the current value of the variable. If the value has not been
* set, and {@code create} is {@code true}, then the {@link #create()}
* method is called, the value of the {@link ThreadLocal} is set to the
* return value of {@link #create()}, and is returned from this method. If
* the value has not been set, and {@code create} is {@code false}, then
* this method behaves exactly the same as the {@link #get()} method.
*
* @return the current value of the variable, or the default value if
* {@code create} is {@code true}.
*
* @param create whether or not to set the default value if it has not yet
* been set.
*/
public T get(boolean create)
{
T t = get();
if (t == null && create){
t = create();
set(t);
}
return t;
} /**
* Sets the current value. If {@code value} is {@code null}, then this
* {@link ThreadLocal} is removed from the thread.
* @param value The value to set.
*/
@Override
public void set(T value)
{
if (value == null){
remove();
}else{
super.set(value);
}
} /**
* Returns the default value for this object.
* @return the default value for this object.
* @see #get(boolean)
*/
protected abstract T create();
}

How to correctly handle ThreadLocal.get() returning null的更多相关文章

  1. correctly handle PNG transparency in Win IE 5.5 & 6.

    function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6. { var arVersion = ...

  2. How to use System.Diagnostics.Process correctly

    I’ve seen many a question on stackoverflow and other places about running a process and capturing it ...

  3. ThreadLocal以及内存泄漏

    ThreadLocal是什么 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用Thr ...

  4. Java -- 基于JDK1.8的ThreadLocal源码分析

    1,最近在做一个需求的时候需要对外部暴露一个值得应用  ,一般来说直接写个单例,将这个成员变量的值暴露出去就ok了,但是当时突然灵机一动(现在回想是个多余的想法),想到handle源码里面有使用过Th ...

  5. ThreadLocal 原理

    ThreadLocal是什么 ThreadLocal是一个本地线程副本变量工具类.主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用, ...

  6. 多线程之ThreadLocal类

    深入研究java.lang.ThreadLocal类 0.前言 ThreadLocal(线程变量副本)Synchronized实现内存共享,ThreadLocal为每个线程维护一个本地变量.采用空间换 ...

  7. ThreadLocal 工作原理、部分源码分析

    1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...

  8. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  9. ThreadLocal 源码剖析

    ThreadLocal是Java语言提供的用于支持线程局部变量的类.所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量(每个线程一个拷贝).在各个Java web的各种框架 ...

随机推荐

  1. Ng第十五课:异常检测(Anomaly Detection)

    15.1  问题的动机 15.2  高斯分布 15.3  算法 15.4  开发和评价一个异常检测系统 15.5  异常检测与监督学习对比 15.6  选择特征 15.7  多元高斯分布(可选) 15 ...

  2. Ubuntu Remove Mysql.service in Systemctl

    After installing MySQL 5.7, I do not want to start MySQL via systemctl. It's unconvenient and compli ...

  3. Mac使用终端安装Homebrew(brew)

    Homebrew简称brew,OSX上的软件包管理工具,在Mac终端可以通过brew安装.更新.卸载软件. 1.打开终端直接输入下面指令回车: // ruby -e "$(curl -fsS ...

  4. 第73讲:Scala界面和事件处理编程进阶实战

    今天学习了王家林老师讲解的scala编程的第73讲,主要是文件选择器的使用.让我们通过代码来亲身体验一下. import scala.swing._import java.io.Fileimport ...

  5. iOS 5 故事板进阶(1)

    译自<iOS 5 by tutorials> 在上一章,你已经学习了故事板的基本用法.包括如何向故事板中添加 View Controller,通过 segues 切换 View Contr ...

  6. Java-动态代理技术

    1.程序中的代理 为具有相同接口的目标类的各个方法,添加一些系统功能,如日志,异常处理,计算方法运行的 时间,事务管理等等,都可以交给另一个类去实现这些功能,该类称为代理类. 注意:为了让代理类共享目 ...

  7. Android-Kotlin-继承

    上一篇博客 Android-Kotlin-配置/入门 配置好了 AndroidStudio Kotlin 的环境: 1.先看一个案例,子类使用到父类的资源 [案例一] 父类 张翠山: package ...

  8. Django:查询后,分页功能为全部对象分页,丢失查询查询参数

    问题: 原始的链接为 http://127.0.0.1:8000/article/list-article-titles-bysomeone/guchen/?column=django 有一个colu ...

  9. dialog里屏蔽ESC和回车

    重载PreTranslateMessage,在return之前加一句判断,只要是按下ESC和回车的消息,就直接置之不理即可,代码如下: if( pMsg->message == WM_KEYDO ...

  10. SpringBoot使用ModelAndView时配置视图解析器

    spring boot 使用视图modelandview 原文:https://www.cnblogs.com/liyafei/p/7955943.html 1:springboot使用视图解析器,添 ...