ThreadLocal 简单介绍
2016-04-13 22:15
399 查看
Threadlocal:当前线程副本
具体定义:当使用ThreadLocal维护变量时,ThreadLocal为每一个使用该变量的线程提供独立的变量副本。
这样每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
从线程的角度看:目标变量就像是线程的本地变量,这样类名中"Local"所要表达的含义
先看看一个案例
public class ThreadLocalTest {
//-------------ThreadLocal修饰的对象----------
private static ThreadLocal<Integer> threadLcoalNum = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 0;
}
};
public int getThreadLocalObject(){
threadLcoalNum.set(threadLcoalNum.get()+1);
return threadLcoalNum.get();
}
//-------------非ThreadLocal修饰的对象----------
private Integer NothreadLcoalNum = 1;
public Integer getNothreadLocalObject(){
return NothreadLcoalNum++;
}
//测试
public static void main(String[] args) {
ThreadLocalTest th = new ThreadLocalTest();
TestClient testClient = new TestClient(th);
new Thread(testClient).start();
new Thread(testClient).start();
}
}
public class TestClient implements Runnable{
private ThreadLocalTest threadLocalTest;
public TestClient(ThreadLocalTest threadLocalTest){
this.threadLocalTest = threadLocalTest;
}
@Override
public void run() {
for(int i=0;i<3;i++){
//threadlcoal 变量测试
System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getThreadLocalObject());
//非threadlcoal 变量测试
System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getNothreadLocalObject());
}
}
}
结果集
----使用ThreadLocal
Thread-0:1
Thread-1:1
Thread-0:2
Thread-1:2
Thread-0:3
Thread-1:3
---未使用
Thread-0:1
Thread-1:2
Thread-0:3
Thread-1:4
Thread-0:5
Thread-1:6
从结果集中我们可以看到2个线程之间的变量是毫无影响的。奇怪呀!!!感觉ThreadLocal好强大的
我们来看看ThreadLocal<T>的类
void set(T value) 设置当前线程的线程局部变量的值
void T get() 该方法返回当前线程所对应的线程局部变量
protected T initialValue() 初始化 用protected 显然是为了子类准备,我在代码中有使用
public void remove() 删除当前线程的局部变量
分析主要方法:
ThreadLocal的set/get 方法源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
上述的set方法中,我们看到了ThreadLocalMap是来自当前的线程,而map里面的key值是this指向是Threadlocal对象,value就是你所设置的对象。
在网上查询资料时候,发现有人说map的key是当前线程,很是迷糊...有点不解。
所以ThreadLocal实现,可以这样的理解:
1.每个线程带了一个ThreadLocalMap,在map中key值是ThreadLocal对象,value值就是你所设置的对象。
2.下次这个线程来请求这个资源时候,通过ThreadLocal的get() 获取这个线程的map。
3.在map中根据当前对象(ThreadLocal对象)作为key值,获取你之前所设置的对象。
这样大家就相互不干扰,皆大欢喜了。
具体定义:当使用ThreadLocal维护变量时,ThreadLocal为每一个使用该变量的线程提供独立的变量副本。
这样每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
从线程的角度看:目标变量就像是线程的本地变量,这样类名中"Local"所要表达的含义
先看看一个案例
public class ThreadLocalTest {
//-------------ThreadLocal修饰的对象----------
private static ThreadLocal<Integer> threadLcoalNum = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 0;
}
};
public int getThreadLocalObject(){
threadLcoalNum.set(threadLcoalNum.get()+1);
return threadLcoalNum.get();
}
//-------------非ThreadLocal修饰的对象----------
private Integer NothreadLcoalNum = 1;
public Integer getNothreadLocalObject(){
return NothreadLcoalNum++;
}
//测试
public static void main(String[] args) {
ThreadLocalTest th = new ThreadLocalTest();
TestClient testClient = new TestClient(th);
new Thread(testClient).start();
new Thread(testClient).start();
}
}
public class TestClient implements Runnable{
private ThreadLocalTest threadLocalTest;
public TestClient(ThreadLocalTest threadLocalTest){
this.threadLocalTest = threadLocalTest;
}
@Override
public void run() {
for(int i=0;i<3;i++){
//threadlcoal 变量测试
System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getThreadLocalObject());
//非threadlcoal 变量测试
System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getNothreadLocalObject());
}
}
}
结果集
----使用ThreadLocal
Thread-0:1
Thread-1:1
Thread-0:2
Thread-1:2
Thread-0:3
Thread-1:3
---未使用
Thread-0:1
Thread-1:2
Thread-0:3
Thread-1:4
Thread-0:5
Thread-1:6
从结果集中我们可以看到2个线程之间的变量是毫无影响的。奇怪呀!!!感觉ThreadLocal好强大的
我们来看看ThreadLocal<T>的类
void set(T value) 设置当前线程的线程局部变量的值
void T get() 该方法返回当前线程所对应的线程局部变量
protected T initialValue() 初始化 用protected 显然是为了子类准备,我在代码中有使用
public void remove() 删除当前线程的局部变量
分析主要方法:
ThreadLocal的set/get 方法源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
上述的set方法中,我们看到了ThreadLocalMap是来自当前的线程,而map里面的key值是this指向是Threadlocal对象,value就是你所设置的对象。
在网上查询资料时候,发现有人说map的key是当前线程,很是迷糊...有点不解。
所以ThreadLocal实现,可以这样的理解:
1.每个线程带了一个ThreadLocalMap,在map中key值是ThreadLocal对象,value值就是你所设置的对象。
2.下次这个线程来请求这个资源时候,通过ThreadLocal的get() 获取这个线程的map。
3.在map中根据当前对象(ThreadLocal对象)作为key值,获取你之前所设置的对象。
这样大家就相互不干扰,皆大欢喜了。
相关文章推荐
- 用wampserver中的phpMyAdmin时会提示 Access denied(访问被拒绝)
- leetcode——22——Generate Parentheses
- 浅谈如何在MySQL中进行模糊搜索的一些问题
- java学习笔记(十)
- Python装饰器
- 【Android】工具 —— Eclipse常用功能
- POJ 3320 Jessica's Reading Problem
- stream 流是什么?
- 百度宣布成立“百度搜索公司”
- 百度宣布成立“百度搜索公司”
- 编码-京东实习笔试编程题-生日礼物-动态规划
- [leetcode]328. Odd Even Linked List
- HTML简介
- 阿里笔试题
- 爆打团队 2016.04.13 站立会议
- Android Studio获取SHA1值
- 03-树2 List Leaves (25分)
- Java操作Redis数据库方法(简单)
- 学习,复习
- HTML文档类型