java中threadlocal的理解
[TOC]
#java中threadlocal的理解
##一、threadlocal的生命周期和ThreadLocalMap的生命周期
可以吧TreadLocal看做是一个map来使用,只不过这个map是指向当前线程中的threadLocals(ThreadLocalMap.class),这个threadLocals采用懒汉单例在一个线程中是唯一的。
Thread中的threadLocals属性,存放的是当前线程在不同TreadLocal实例中的值ThreadLocalMap<TreadLocal,T>
```java
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。
```java
ThreadLocal local1 = new ThreadLocal();
local.remove();
```
##二、ThreadLocal的作用
对于那些需要数据隔离,可以用ThreadLocal。
对于一个线程中的一个ThreadLocal只能存一个T类型的数据。(T为泛型)
ThreadLocal是线程安全的,所以可以用来封装线程不安全的实例,不同线程之间新创建实例,保证线程安全。(另一种模式就是单例模式。)
##三、threadlocal示例
1. 比较经典的例子就是github中的PageHelper中保存Page信息的时候使用了ThreadLocal。考虑到数据的同步,已经一个线程只会顺序执行sql语句。
```java
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal();
protected static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}
```
2. AopContext
在同一个类中调用方法,导致aop不生效。原因是aop生效是调用的代理类,直接调用被代理类会无法触发切面。
```java
@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中的值进行复制
```java
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);
......略
}
}
```
5. 和threallocal相比,只有map的引用不一样。
java中threadlocal的理解的更多相关文章
- java中ThrealLocal的理解
目录 java中threadlocal的理解 一.threadlocal的生命周期和ThreadLocalMap的生命周期 二.ThreadLocal的作用 三.threadlocal示例 四.Inh ...
- 谈谈我对Java中CallBack的理解
谈谈我对Java中CallBack的理解 http://www.cnblogs.com/codingmyworld/archive/2011/07/22/2113514.html CallBack是回 ...
- 沉淀再出发:关于java中的AQS理解
沉淀再出发:关于java中的AQS理解 一.前言 在java中有很多锁结构都继承自AQS(AbstractQueuedSynchronizer)这个抽象类如果我们仔细了解可以发现AQS的作用是非常大的 ...
- Java中hashcode的理解
Java中hashcode的理解 原文链接http://blog.csdn.net/chinayuan/article/details/3345559 怎样理解hashCode的作用: 以 java. ...
- java中ThreadLocal的使用
文章目录 在Map中存储用户数据 在ThreadLocal中存储用户数据 java中ThreadLocal的使用 ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问. 在定 ...
- java中ThreadLocal类的使用
ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复, ...
- 关于java中多态的理解
java三大特性:封装,继承,多态. 多态是java的非常重要的一个特性: 那么问题来了:什么是多态呢? 定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行 ...
- Java中ThreadLocal的设计与使用
早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...
- Java中泛型的理解
Java中的泛型,本质上来说,就是是参数化类型,就是说所操作的数据类型被指定为一个参数,而不是确定的某种类型.这种数据类型可以用在类.接口和方法创建中.即泛型类.泛型接口.泛型方法.这样说可能不够生动 ...
随机推荐
- 对掌机游戏Pokemon的一部分系统的拆解流程图
整体系统拆解 POKEMON系统拆解 属性.技能.进化形态 属性提升系统 种族值说明: 所有Pokemon都拥有自己的种族的种族值,且固定(例如:小火龙:309, 皮卡丘: 320) 种族值是各项属性 ...
- bzoj3891[Usaco2014 Dec]Piggy Back*
bzoj3891[Usaco2014 Dec]Piggy Back 题意: 给定一个N个点M条边的无向图,其中Bessie在1号点,Elsie在2号点,它们的目的地为N号点.Bessie每经过一条边需 ...
- CCNA-Part4 -网络层 - IP 协议了解一下
网络层主要提供寻址,路由的功能.而 IP 协议就是为了实现该功能而设计的. IP 协议 IP 协议的特性 工作在网络层 面向无连接的协议 具有单独处理包的能力 分层的地址 不可靠,尽力而为的传送 独立 ...
- redis入门指南(六)—— 集群
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 配置集群 1.配置集群,集群解决了单点故障以及单台机器内存上限的问题,使用集群时,只需要将配置文 ...
- 文件传输协议---TFTP
简介 TFTP协议全称为简单文件传输协议,是以UDP为基础的应用层协议,主要用于不同设备之间的文件传输.具有协议简单,易于实现的特点,常用于嵌入式设备开发中. 传输模式 数据的存储有不同的格式,磁盘中 ...
- Python之threading初探
threading库主要用于基于线程的并行,核心就是Thread类 class threading.Thread(group=None, target=None, name=None, args= ...
- vue-过渡动画和 第三方动画库导入,带图
vue路由过渡动画 //用transition将路由出口包裹起来 <transition name="fade" mode="out-in"> &l ...
- AndroidStudio查找硬编码的String字符串
在Menu的“Analyze”中,选择“Run Inspection By Name”,然后输入“Hardcoded strings”,执行后,可以找到所有没有加入strings.xml的字符串. 按 ...
- adb连接多个设备时,选择某个设备
在emulator-5554模拟器上安装ebook.apk: adb -s emulator-5554 install ebook.apk 在真机上安装ebook.apk: adb -s HT9BYL ...
- web自动化 -- 浏览器窗口切换
切换浏览器窗口 示例: from time import sleep from selenium import webdriver from selenium.webdriver.support.wa ...