博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ThreadLocal类
阅读量:6902 次
发布时间:2019-06-27

本文共 2913 字,大约阅读时间需要 9 分钟。

彻底理解ThreadLocal

 

ThreadLocalMap类的定义是在ThreadLocal类中,真正的引用却是在Thread类中。同时,ThreadLocalMap中用于存储数据的entry定义。

 

Map的key是ThreadLocal类的实例对象,value为用户的值,并不是网上大多数的例子key是线程的名字或者标识

A.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);    }    public T get() {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }

B.getMap方法

ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }

C.给当前Thread类对象初始化ThreadlocalMap属性:

void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }

 

ThreadLocal变量的活动范围为某线程,是该线程“专有的,独自霸占”的,对该变量的所有操作均由该线程完成!也就是说,ThreadLocal 不是用来解决共享对象的多线程访问的竞争问题的,因为ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。当线程终止后,这些值会作为垃圾回收。

由ThreadLocal的工作原理决定了:每个线程独自拥有一个变量,并非是共享的,下面给出一个例子:

public class Son implements Cloneable{    public static void main(String[] args){        Son p=new Son();        System.out.println(p);        Thread t = new Thread(new Runnable(){              public void run(){                ThreadLocal
threadLocal = new ThreadLocal<>(); System.out.println(threadLocal); threadLocal.set(p); System.out.println(threadLocal.get()); threadLocal.remove(); try { threadLocal.set((Son) p.clone()); System.out.println(threadLocal.get()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } System.out.println(threadLocal); }}); t.start(); }}  

输出:

Son@7852e922java.lang.ThreadLocal@3ffc8195Son@7852e922Son@313b781ajava.lang.ThreadLocal@3ffc8195

也就是如果把一个共享的对象直接保存到ThreadLocal中,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 所以要在保存到ThreadLocal之前,通过克隆或者new来创建新的对象,然后再进行保存。

  ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用。作用:提供一个线程内公共变量(比如本次请求的用户信息),减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度,或者为线程提供一个私有的变量副本,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

 

 

总之,ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点: 

1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。 
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。 
当然如果要把本来线程共享的对象通过ThreadLocal.set()放到线程中也可以,可以实现避免参数传递的访问方式,但是要注意get()到的是那同一个共享对象,并发访问问题要靠其他手段来解决。但一般来说线程共享的对象通过设置为某类的静态变量就可以实现方便的访问了,似乎没必要放到线程中。 

 

 

 ThreadLoacl实例:

 

  

  

 

转载于:https://www.cnblogs.com/ningshare/p/10683746.html

你可能感兴趣的文章
完全卸载oracle
查看>>
汇编----指令(一)
查看>>
我的友情链接
查看>>
在虚拟机上安装centos7
查看>>
【C#】string.format 应用
查看>>
地图检索 – 与众不同
查看>>
nginx 配置实战:流量及并发连接数限制
查看>>
关于logrotate的额外补充
查看>>
我的友情链接
查看>>
图解自定义安装CentOS
查看>>
Xposed hook(android)
查看>>
vs设置异常就断下
查看>>
win7 共享打印机后,客户端连接提示:打印机已删除(0x00000709)
查看>>
工作与生活之平衡(4)微博病患者
查看>>
Andriod第七课-----数据库
查看>>
Shell使用for循环语句
查看>>
ASP.NET设计的几个技巧
查看>>
电脑爱好者GHOSTWIN7纯净版V1.0
查看>>
Bootstrap3系列:输入框组
查看>>
刘启成_第七章实验(四):case
查看>>