java中threadlocal的理解

一、threadlocal的生命周期和ThreadLocalMap的生命周期

可以吧TreadLocal看做是一个map来使用,只不过这个map是指向当前线程中的threadLocals(ThreadLocalMap.class),这个threadLocals采用懒汉单例在一个线程中是唯一的。

Thread中的threadLocals属性,存放的是当前线程在不同TreadLocal实例中的值ThreadLocalMap<TreadLocal,T>

 public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//return t.threadLocals;这里表示只有一个ThreadLocalMap副本
if (map != null)//采用懒汉模式
map.set(this, value);
else
createMap(t, value);//t.threadLocals = new ThreadLocalMap(this, firstValue);
}

可以通过查看当前线程中的threadLocals变量,来看当前线程持有多少个threadLocal,以及存的值。

ThreadLocalMap实例的生命周期随着线程的结束而结束,因为ThreadLocalMap实例的唯一引用只存在当前线程中。ThreadLocal的生命周期,需要gc来决定,因为他的引用可能存在于多个线程中,此引用为弱引用。

弱引用的存在,导致可能内存泄露。当threadlocal=null,没有任何强引用实例指向threadLocals中的key本来指向的threadlocal实例,gc回收threadlocal,导致val永远不会被释放。采用以下代码来取代=null的操作,用remove函数来清除,threadLocals。

ThreadLocal local1 = new ThreadLocal();
local.remove();

二、ThreadLocal的作用

对于那些需要数据隔离,可以用ThreadLocal。

对于一个线程中的一个ThreadLocal只能存一个T类型的数据。(T为泛型)

ThreadLocal是线程安全的,所以可以用来封装线程不安全的实例,不同线程之间新创建实例,保证线程安全。(另一种模式就是单例模式。)

三、threadlocal示例

  1. 比较经典的例子就是github中的PageHelper中保存Page信息的时候使用了ThreadLocal。考虑到数据的同步,已经一个线程只会顺序执行sql语句。
 protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();
protected static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}
  1. AopContext

    在同一个类中调用方法,导致aop不生效。原因是aop生效是调用的代理类,直接调用被代理类会无法触发切面。
@EnableAspectJAutoProxy(exposeProxy = true)//打开代理配置Appcontext

AopContext.currentProxy() //获取到当前类的代理类,可以进行强制转换

public abstract class AopContext {
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal("Current AOP proxy");//本质还是通过threadlocal实现
public AopContext() {
}
public static Object currentProxy() throws IllegalStateException {
Object proxy = currentProxy.get();
if (proxy == null) {
throw new IllegalStateException("Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
} else {
return proxy;
}
} static Object setCurrentProxy(Object proxy) {
Object old = currentProxy.get();
if (proxy != null) {
currentProxy.set(proxy);
} else {
currentProxy.remove();
} return old;
}
}

四、InheritableThreadLocal的扩展

  1. InheritableThreadLocal extends ThreadLocal
  2. 子线程可以使用InheritableThreadLocal可以拿到父亲线程的变量,父线程无法拿到子线程的
  3. 子线程对变量的修改,父线程不可见。子线程修改的父线程那边拷贝的副本
  4. init子线程的时候,对threadlocal中的值进行复制
class Thread{
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
......略
Thread parent = currentThread();
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
......略
}
}
  1. 和threallocal相比,只有map的引用不一样。

java中ThrealLocal的理解的更多相关文章

  1. java中threadlocal的理解

    [TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...

  2. 谈谈我对Java中CallBack的理解

    谈谈我对Java中CallBack的理解 http://www.cnblogs.com/codingmyworld/archive/2011/07/22/2113514.html CallBack是回 ...

  3. 沉淀再出发:关于java中的AQS理解

    沉淀再出发:关于java中的AQS理解 一.前言 在java中有很多锁结构都继承自AQS(AbstractQueuedSynchronizer)这个抽象类如果我们仔细了解可以发现AQS的作用是非常大的 ...

  4. Java中hashcode的理解

    Java中hashcode的理解 原文链接http://blog.csdn.net/chinayuan/article/details/3345559 怎样理解hashCode的作用: 以 java. ...

  5. 关于java中多态的理解

    java三大特性:封装,继承,多态. 多态是java的非常重要的一个特性: 那么问题来了:什么是多态呢? 定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行 ...

  6. Java中泛型的理解

    Java中的泛型,本质上来说,就是是参数化类型,就是说所操作的数据类型被指定为一个参数,而不是确定的某种类型.这种数据类型可以用在类.接口和方法创建中.即泛型类.泛型接口.泛型方法.这样说可能不够生动 ...

  7. 浅谈对java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

  8. Java中面向对象的理解

    按照惯例,先做一个简单的介绍,现在开始学习 Thinging in Java 4 ,一边看,一边记录,我都不想给自己设定时间安排了,毕竟很少实现过.所以就这样吧!不定期的更新,我都会放到博客中的. 所 ...

  9. java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

随机推荐

  1. 2. import 与 from...import 导入模块

    1. 导入整个模块 格式: import somemodule2. 从某个模块中导入某个函数 格式: from somemodule import somefunction3. 从某个模块中导入多个函 ...

  2. 如何将 Bitbucket 的 pull request 签出到本地 review

    将 pull request 签出到本地进行 review, 最大的好处是可以通过 IDE 来查找各种变量和方法的上下文引用,以便充分发挥我们杠精的本领,将 pull request 中的各种合理和不 ...

  3. pom.xml文件中的parent标签

    基本概念 maven的核心就算pom.xm,使用maven是为了更好地帮项目管理包依赖.如果要引入一个jar包,需要在pom文件中加上 <dependency> <groupId&g ...

  4. Monster Audio 使用教程 (七) 防止声音过大,出现爆音

    有用户反映,如果音乐音量过大,会出现爆音. 这其实是音频信号过载了.只要最后输出的音量超过0db,就会出现爆音,这是数字音频都应该注意的问题. 所以,为了解决这个问题,限制器就出现了,它能把音频信号压 ...

  5. .Net Core AES加解密

    项目中token在传输过程中采用了AES加密,  网上找到的两篇博文都有写问题,在这里记录一下.Net Core 2.2代码中AES加解密的使用: //AES加密 传入,要加密的串和, 解密key p ...

  6. jenkins集群(三) -- master和slave配置git

    一.Linux(master)上安装git 1.运行命令:yum -y install git 2.git的默认安装目录是:  二.给Linux下Git配置好秘钥(公钥 + 私钥) 1.添加用户和密码 ...

  7. 题解 P1201 【[USACO1.1]贪婪的送礼者Greedy Gift Givers】

    这一题挺简单的,但是如果是纯模拟的话.会十分麻烦 这里介绍一个\(STL\)映射\(map\) \(map\)的最大优点是可以使用任意数据类型作为数组的下标 \(map\)的定义形式为 map< ...

  8. Java基础知识_内存

    前述:利用一段较为充足暑假时间,对以前的Java学习进行一个系统性的回顾,对于部分知识点进行记录和积累. Java中的内存 一 Java中的内存划分: Java中内存主要划分为五部分 栈(Stack) ...

  9. 【Python】Async异步等待简单例子理解

    import time def run(coroutine): try: print("") coroutine.send(None) except StopIteration a ...

  10. flask中的endpoint是什么

    app.view_functions 是一个字典,里面是存储的是 endpoint 与 视图函数的键值对,如果没指名函数视图的endpoint,默认是函数名,而 url_map 是一个列表,里面是ur ...