知识大全 深入ThreadLocal
Posted 变量
篇首语:我们要像海绵一样吸收有用的知识。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 深入ThreadLocal相关的知识,希望对你有一定的参考价值。
Java线程:深入ThreadLocal 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
ThreadLocal与线程成员变量还有区别 ThreadLocal该类提供了线程局部变量 这个局部变量与一般的成员变量不一样 ThreadLocal的变量在被多个线程使用时候 每个线程只能拿到该变量的一个副本 这是Java API中的描述 通过阅读API源码 发现并非副本 副本什么概念?克隆品? 或者是别的样子 太模糊
准确的说 应该是ThreadLocal类型的变量内部的注册表(Map<Thread T>)发生了变化 但ThreadLocal类型的变量本身的确是一个 这才是本质!
下面就做个例子
一 标准例子
定义了MyThreadLocal类 创建它的一个对象tlt 分别给四个线程使用 结果四个线程tlt变量并没有出现共用现象 二是各用各的 这说明 四个线程使用的是tlt的副本(克隆品)
/**
* 使用了ThreadLocal的类
*
* @author leizhimin : :
*/
public class MyThreadLocal
//定义了一个ThreadLocal变量 用来保存int或Integer数据
private ThreadLocal<Integer> tl = new ThreadLocal<Integer>()
@Override
protected Integer initialValue()
return ;
;
public Integer getNextNum()
//将tl的值获取后加 并更新设置t 的值
tl set(tl get() + );
return tl get();
/**
* 测试线程
*
* @author leizhimin : :
*/
public class TestThread extends Thread
private MyThreadLocal tlt = new MyThreadLocal();
public TestThread(MyThreadLocal tlt)
this tlt = tlt;
@Override
public void run()
for (int i = ; i < ; i++)
System out println(Thread currentThread() getName() + \\t + tlt getNextNum());
/**
* ThreadLocal测试
*
* @author leizhimin : :
*/
public class Test
public static void main(String[] args)
MyThreadLocal tlt = new MyThreadLocal();
Thread t = new TestThread(tlt);
Thread t = new TestThread(tlt);
Thread t = new TestThread(tlt);
Thread t = new TestThread(tlt);
t start();
t start();
t start();
t start();
可以看出 三个线程各自独立编号 互不影响
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Process finished with exit code
tlt对象是一个 废话tl对象也是一个 因为组合关系是一对一的 但是tl对象内部的Map随着线程的增多 会创建很多Integer对象 只是Integer和int已经通用了 所以感觉不到Integer的对象属性
二 不用ThreadLocal
假如不用ThreadLocal 只需要将MyThreadLocal类重新定义为
/**
* 使用了ThreadLocal的类
*
* @author leizhimin : :
*/
public class MyThreadLocal
private Integer t = ;
public Integer getNextNum()
return t =t + ;
// //定义了一个ThreadLocal变量 用来保存int或Integer数据
// private ThreadLocal<Integer> tl = new ThreadLocal<Integer>()
// @Override
// protected Integer initialValue()
// return ;
//
// ;
//
// public Integer getNextNum()
// //将tl的值获取后加 并更新设置t 的值
// tl set(tl get() + );
// return tl get();
//
然后运行测试
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Process finished with exit code
从这里可以看出 四个线程共享了tlt变量 结果每个线程都直接修改tlt的属性
三 自己实现个ThreadLocal
package lavasoft test ;
import java util Collections;
import java util HashMap;
import java util Map;
/**
* 使用了ThreadLocal的类
*
* @author leizhimin : :
*/
public class MyThreadLocal
//定义了一个ThreadLocal变量 用来保存int或Integer数据
private lavasoft test ThreadLocal<Integer> tl = new lavasoft test ThreadLocal<Integer>()
@Override
protected Integer initialValue()
return ;
;
public Integer getNextNum()
//将tl的值获取后加 并更新设置t 的值
tl set(tl get() + );
return tl get();
class ThreadLocal<T>
private Map<Thread T> map = Collections synchronizedMap(new HashMap<Thread T>());
public ThreadLocal()
protected T initialValue()
return null;
public T get()
Thread t = Thread currentThread();
T obj = map get(t);
if (obj == null && !ntainsKey(t))
obj = initialValue();
map put(t obj);
return obj;
public void set(T value)
map put(Thread currentThread() value);
public void remove()
map remove(Thread currentThread());
运行测试
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Process finished with exit code
很意外 这个山寨版的ThreadLocal也同样运行很好 实现了JavaAPI中ThreadLocal的功能
四 透过现象看本质
其实从程序角度看 tlt变量的确是一个 毫无疑问的 但是为什么打印出来的数字就互不影响呢?
是因为使用了Integer吗? 不是
原因是 protected T initialValue()和get() 因为每个线程在调用get()时候 发现Map中不存在就创建 调用它的时候 就创建了一个新变量 类型为T 每次都新建 当然各用个的互不影响了
为了看清本质 将Integer换掉 重写部分类
package lavasoft test ;
import java util Collections;
import java util HashMap;
import java util Map;
/**
* 使用了ThreadLocal的类
*
* @author leizhimin : :
*/
public class MyThreadLocal
//定义了一个ThreadLocal变量 用来保存int或Integer数据
// private ThreadLocal<Bean> tl = new ThreadLocal<Bean>()
private lavasoft test ThreadLocal<Bean> tl = new lavasoft test ThreadLocal<Bean>()
@Override
protected Bean initialValue()
return new Bean();
;
@Override
public String toString()
return MyThreadLocal +
tl= + tl +
;
public Bean getBean()
return tl get();
class ThreadLocal<T>
private Map<Thread T> map = Collections synchronizedMap(new HashMap<Thread T>());
public ThreadLocal()
protected T initialValue()
return null;
public T get()
Thread t = Thread currentThread();
T obj = map get(t);
if (obj == null && !ntainsKey(t))
obj = initialValue();
map put(t obj);
return obj;
public void set(T value)
map put(Thread currentThread() value);
public void remove()
map remove(Thread currentThread());
package lavasoft test ;
/**
* 测试Bean
*
* @author leizhimin : :
*/
public class Bean
private String id = ;
private String name = none ;
public Bean()
public Bean(String id String name)
this id = id;
this name = name;
public String getId()
return id;
public void setId(String id)
this id = id;
public String getName()
return name;
public void setName(String name)
this name = name;
public String showinfo()
return Bean +
id= + id + \\ +
name= + name + \\ +
;
package lavasoft test ;
/**
* 测试线程
*
* @author leizhimin : :
*/
public class TestThread extends Thread
private MyThreadLocal tlt = new MyThreadLocal();
public TestThread(MyThreadLocal tlt)
this tlt = tlt;
@Override
public void run()
System out println( >>>>>: + tlt);
for (int i = ; i < ; i++)
System out println(Thread currentThread() getName() + \\t +tlt getBean()+ \\t +tlt getBean() showinfo());
然后运行测试
>>>>>:MyThreadLocaltl= lavasoft test MyThreadLocal$ @ de f d
>>>>>:MyThreadLocaltl= lavasoft test MyThreadLocal$ @ de f d
>>>>>:MyThreadLocaltl= lavasoft test MyThreadLocal$ @ de f d
>>>>>:MyThreadLocaltl= lavasoft test MyThreadLocal$ @ de f d
Thread lavasoft test Bean@ aff Beanid= name= none
Thread lavasoft test Bean@fe b Beanid= name= none
Thread lavasoft test Bean@ db Beanid= name= none
Thread lavasoft test Bean@fe b Beanid= name= none
Thread lavasoft test Bean@fe b Beanid= name= none
Thread lavasoft test Bean@ aff Beanid= name= none
Thread lavasoft test Bean@ db Beanid= name= none
Thread lavasoft test Bean@ db Beanid= name= none
Thread lavasoft test Bean@ aff Beanid= name= none
Thread lavasoft test Bean@ aff Beanid= name= none
Thread lavasoft test Bean@ aff Beanid= name= none
Thread lavasoft test Bean@ aff Beanid= name= none
Process finished with exit code
cha138/Article/program/Java/gj/201311/27562相关参考
Java并发编程实践之ThreadLocal变量 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
深入解剖LILO 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 本文我们将深入底层来讲述LILO
EclipseGanymede:深入RAP 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 作为即
深入浅出Hibernate的属性查询 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 《深入浅出H
麦克连指标深入讲解顺势操作依剑法1、2的说明,读者了解MCL是一种超买超卖指标,市场处于“常态行情”时,股民采用“低买高卖”策略,似乎相当合理。但是,众所皆知,行情的波动不可能如此理想化,市场经常出现
深入了解String 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一从根本上认识javalangS
知识大全 深入解析contentWindow, contentDocument
深入解析contentWindow,contentDocument 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一
C#高级编程:数据绑定深入理解[3] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
C#高级编程:数据绑定深入理解[4] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
C#高级编程:数据绑定深入理解[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n