您的位置:首页 > 编程语言 > Java开发

java ThreadLocal 自己的一些见解

2016-05-18 17:29 309 查看

别人的ThreadLocal

一开始学的时候就直接去百度了,找了很多的说明和代码样例。
我个人的学习习惯是先看说明,要精简扼要的那种,让我看了就能理解这是个什么东西,有什么用,然后根据实际的例子去理解。
这里先复制写网上很容易就可以找到的说明吧。


ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

大概差不多都是这样的,可以总结为几点:
1. ThreadLocal不是Thread
2. 每个线程都有一个自己的ThreadLocal
3. 不同的线程的ThreadLocal里面放的是同一个变量的不同副本,从而使得线程之间不会出现资源争抢的情况


然后看了看样例代码,直接就自己写了一个,样例中的资源是一个是整型数据,我觉得那太简单,就直接写了个简单的类,Person有name,age。照着例子搬了过来,结果各种空指针异常。

我的ThreadLocal

我自己写代码测试的过程是这样计划的:

1程序. 写个正常的(或者说有错误的)多线程处理的代码,没有同步机制,也没有ThreadLocal,结果肯定不是预期的

2程序. 改写成同步机制的,结果是对的

3程序. 最后改成ThreadLocal的,结果也是对的,然后把2和3对比对比

代码情况大概如下:

测试类(main方法)

线程类(创建多线程用的)

资源类(Person,被争抢的对象)

样例代码都是一个类把我上面3个类搞定了,测试类本身就实现了奔跑接口,可以当线程用,资源也是基础类型,直接一个成员变量代替了,我觉得看着乱,不够清楚,就直接分成了3个类。

main方法首先是一个资源对象Person p,然后是两个线程对象的实例,接收同一个p到自己的线程内部进行处理。

1程序搞定,

2程序,在线程类的run方法里面给用到p的地方加上同步块,搞定

3程序!!!!!

main方法里创建p的上面创建了一个ThreadLocal对象local,然后把p set进去,然后把local传到线程类里进行操作,线程里之前操作p的地方都替换成了local的get和set。

结果就是一堆的空指针异常。

满脑子想:“同一个变量的不同副本, 我local里面set一个p,然后每个线程里get的p都是之前线程争抢的资源p的一个副本,然后各个线程互不影响。。。。”

然后脑子疼,自己代码跑不通。。。

再就不停的反复的看样例代码,后来也找了几个资源类型不是基础类型的样例,

再就是看ThreadLocal的源码,看看是在哪里创建了怎样的一个副本,是不是只对于基本类型起作用,

好久还是没懂,代码还是没跑通。。。

后来又看到了说是整理好的ThreadLocal的工具类,看到在线程里面new了一个新的资源对象放到了ThreadLocal里面!!!!!

我勒个擦,如果在ThreadLocal里面get不到这个资源,就new一个新的放到里面,而且你第一次get的时候肯定是空 的,如果你不提前set的话。 这岂不是说 每个线程的ThreadLocal里面的对象都是不同的实例,完全的不相干的实例,这线程之间想影响也影响不到啊。

顿时彻底乱了。。。

所谓的ThreadLocal和每个线程绑定,里面放的是资源的副本,搞了半天里面是不是副本不是ThreadLocal本身实现的,而是哥自己手动写的,那我不放副本,那就不是副本了!!!

然后开始回想整个的场景,

当多线程开启的时候,而且多个线程共同享用一个资源的时候,是一个资源,一个(可以理解为单例的,要是多个的话也不用抢了),要考虑这个资源是不是真的需要多个线程共享?

如果这个资源是个计数器,多个线程肯定要共享,要不就记乱了

如果这个资源是个球拍,用来打球的话,完全可以复制几个,自己玩自己的

(比喻不是很恰当啊~~~)

如果这个资源是需要多个线程协同作业,以后还有交集,就是需要共享的,要用同步机制;如果这个资源多个线程自己用自己的,影响不到他人,那就用ThreadLocal复制几份

同步机制从1程序改成2程序,看着很顺理成章,可是ThreadLocal的复制机制怎么改成第3个程序就绕了。

最后想了想,所谓的线程之间互不影响,本质上和ThreadLocal没有什么关系,而且new的原因,你在两个线程里面new了两个对象,让他们怎么互相影响?

而ThreadLocal的作用是保证在同一个线程里面,get的对象是同一个对象,保证线程里的单例,它的重点是和线程绑定。

而且写代码的时候,最好把ThreadLocal写在线程对象里面,好理解(ThreadLocal本来就是和线程绑定的),像我写在main里面,main也是一个线程啊。

最后:是ThreadLocal和new决定了每个线程都有资源的一个副本,互不影响,确切的说只有new。

可能是我理解有问题,网上的资料都是那么写的,看来看去我还是糊涂,最后自己安慰自己,也不知道对不对, 欢迎大家讨论指正!!

另外:MD真难用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: