浅析 ThreadLocal
一、ThreadLocal类说明
ThreadLocal,很容易让人望文生义,直译"本地线程"。ThreadLocal不是一个thread,是thread的局部变量。使用ThreadLocal维护变量时,它为每个使用它的线程提供独立的线程副本,每个线程可以改变自己的副本,而不会影响到其它线程对应的副本。
从线程的角度看,目标变量就象是线程的本地变量,这也是类名中"Local"所要表达的意思。
二、ThreadLocal常用方法
①、当前变量的初始值
protected T initialValue()
源码 如下,该方法是一个protected方法,显然是为了让子类覆盖而设计的。该方法是在get|set会调用,且只会被调一次。ThreadLocal缺省实现直接返回null
protected T initialValue() {
return null;
}
②、设置当前线程的线程局部变量值
void set(T value)
③、返回当前线程的线程局部变量值
public T get()
④、删除当前线程的线程局部变量值,节省内存的占用。
public void remove()
三、下面我们通过一个具体例子,看看ThreadLocal的具体用法---Id生成器
id生成器
public interface Sequence {
public int getId();
}
public class LocalSequenceImpl implements Sequence {
private ThreadLocal<Integer> container = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
};
};
@Override
public int getId() {
container.set(container.get() + 1);
return container.get();
}
}
线程
public class ThreadLocalDemo extends Thread {
private static Sequence obj;
@SuppressWarnings("static-access")
public ThreadLocalDemo(Sequence obj) {
this.obj = obj;
}
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " : " + obj.getId());
}
}
public static void main(String[] args) {
Sequence obj = new LocalSequenceImpl();
test(obj);
}
static void test(Sequence obj) {
ThreadLocalDemo thread1 = new ThreadLocalDemo(obj);
ThreadLocalDemo thread2 = new ThreadLocalDemo(obj);
ThreadLocalDemo thread3 = new ThreadLocalDemo(obj);
thread1.start();
thread2.start();
thread3.start();
}
}
结果 :
Thread-0 : 1
Thread-1 : 1
Thread-1 : 2
Thread-2 : 1
Thread-2 : 2
Thread-2 : 3
Thread-1 : 3
Thread-0 : 2
Thread-0 : 3
从上述结果,每个线程只会更改自己的局部变量,并没有发生互相干扰的情况。可以看出来,ThreadLocal为使用它的线程提供独立的副本。
不信?我们下面再通过一个不使用ThreadLocal来验证下。
public class SequenceImpl implements Sequence {
private static int id = 0;
@Override
public int getId() {
id = id + 1;
return id;
}
}
结果
Thread-0 : 2
Thread-0 : 4
Thread-0 : 5
Thread-2 : 3
Thread-2 : 6
Thread-2 : 7
Thread-1 : 1
Thread-1 : 8
Thread-1 : 9
仔细观察下结果,三个线程同时访问一个局部变量id,发生了互相干扰的情况。
四、拓展
看下ThreadLocal源码,底层是用Map实现的。我们可以自己设计一个ThreadLocal
public class MyThreadLocal<T> {
private Map<Thread, T> container = Collections.synchronizedMap(new HashMap<>());
public void set(T value) {
container.put(Thread.currentThread(), value);
}
public T get() {
Thread currentThread = Thread.currentThread();
T value = container.get(Thread.currentThread());
if(value == null && !container.containsKey(currentThread)) {
value = initialValue();
container.put(Thread.currentThread(), value);
}
return value;
}
protected T initialValue() {
return null;
}
}
浅析 ThreadLocal的更多相关文章
- 浅析ThreadLocal
这是我的第一篇博客,条理不是很清晰,不过还是希望能对大家有所帮助. 首先明确一下这个类的作用,ThreadLocal类是用来为每个线程提供了一份变量的副本,即每个线程的局部变量.每个线程都在自己的栈空 ...
- ThreadLocal 从源码角度简单分析
目录 ThreadLcoal源码浅析 ThreadLocal的垃圾回收 Java引用 ThreadLocal的回收 各线程中threadLocalMap的回收 内存泄露问题 总结 参考 ThreadL ...
- Java并发包2--ThreadLocal的使用及原理浅析
ThreadLocal 是本地线程变量,是一个以ThreadLocal对象为key,任意对象为value的存储结构. 一.使用案例 1.定义线程类MyThread,代码如下: public class ...
- ThreadLocal浅析
1.ThreadLocal的大体理解 ThreadLocal 又名 线程局部变量,是 Java 中一种较为特殊的 线程绑定机制,可以为每一个使用该变量的线程都提供一个变量值的副本,并且每一个线程都可以 ...
- 浅析Linux操作系统工作的基础
环境:lubuntu 13.04 kernel 3.9.7 作者:SA12226265 katao 简介: 本文根据 Linux™ 系统工作基础的分析,对存储程序计算机.堆栈(函数调用堆栈)机制和 ...
- spring源码浅析——IOC
=========================================== 原文链接: spring源码浅析--IOC 转载请注明出处! ======================= ...
- ThreadLocal原理分析与代码验证
ThreadLocal提供了线程安全的数据存储和访问方式,利用不带key的get和set方法,居然能做到线程之间隔离,非常神奇. 比如 ThreadLocal<String> thread ...
- 浅析MyBatis(三):聊一聊MyBatis的实用插件与自定义插件
在前面的文章中,笔者详细介绍了 MyBatis 框架的底层框架与运行流程,并且在理解运行流程的基础上手写了一个自己的 MyBatis 框架.看完前两篇文章后,相信读者对 MyBatis 的偏底层原理和 ...
- 老生常谈系列之Aop--Spring Aop原理浅析
老生常谈系列之Aop--Spring Aop原理浅析 概述 上一篇介绍了AspectJ的编译时织入(Complier Time Weaver),其实AspectJ也支持Load Time Weaver ...
随机推荐
- P125、面试题19:二叉树的镜像
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTr ...
- ASCII码表详解
第一部分:ASCII非打印控制字符表 ASCII表上的数字0–31分配给了控制字符,用于控制像打印机等一些外围设备.例如,12代表换页/新页功能.此命令指示打印机跳到下一页的开头.(参详ASCII码表 ...
- 1067. Disk Tree(字符串)
1067 破题啊 写完发现理解错题意了 子目录下会有跟之前重名的 把输入的字符串存下来 排下序 然后依次找跟上面有没有重的 #include <iostream> #include< ...
- 1126. Magnetic Storms(单调队列)
1126 最简单的单调队列应用吧 单调队列是指在一个队列中各个元素单调 递增(或者递减),并且各个元素的下标单调 递增. 单调队列的大体操作 进队时,将进队的元素为e,从队尾往前扫描,直到找到一个不大 ...
- poj3034Whac-a-Mole(dp)
链接 状态转移好想 不过有坑 大家都犯的错误 我也会犯 很正常 就是锤子可以移到n*n以外 要命的是我只加了5 以为最多不会超过5 WA了N久 才想到 上下两方向都可以到5 所以最多加10 以时 ...
- poj 2151 Check the difficulty of problems(概率dp)
poj double 就得交c++,我交G++错了一次 题目:http://poj.org/problem?id=2151 题意:ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 问 ...
- POJ 2318 (叉积) TOYS
题意: 有一个长方形,里面从左到右有n条线段,将矩形分成n+1个格子,编号从左到右为0~n. 端点分别在矩形的上下两条边上,这n条线段互不相交. 现在已知m个点,统计每个格子中点的个数. 分析: 用叉 ...
- UVa 1645 (递推) Count
题意: 有多少个n个节点的有根树,满足每层节点的子节点个数相同,输出该数目除以1e9+7的余数. 分析: 这种题目就属于那种,看起来很高冷,读完题更高冷.想了N久想不出来,一搜题解,卧槽,这么sb的题 ...
- MySQL全世界最流行的开源数据库软件
誉天全国首推全球市场占有率第二的数据库——MySQL培训课程,阿里巴巴.新浪等知名企业正在使用MySQL数据库系统,而这方面的人才需求也是供不应求,誉天作为国内2014年首批ORACLE官方授权MyS ...
- HDU 1503 Advanced Fruits (LCS,变形)
题意: 给两个水果名,要求他们的LCS部分只输出1次,其他照常输出,但是必须保持原来的顺序! 思路: 求LCS是常规的,但是输出麻烦了,要先求LCS,再标记两串中的所有LCS字符,在遇到LCS字符时, ...