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真难用
相关文章推荐
- Java 内部类种类及使用解析
- java web工程启动socket服务
- java.lang.IllegalStateException: Could not find a method false(View) in the activity class com.xuan
- Java学习-30天
- math.random()和Math.round的区别
- springmvc自动转前台传来的时间数据
- Java : java.util.ConcurrentModificationException
- Spring事务传播机制和数据库隔离级别
- java web 项目启动开启 socket server 作者:Mchange
- eclipse错误: 找不到或无法加载主类解决过程
- java初始化顺序
- RabbitMQ 入门指南(Java)
- Java--发牌程序(一对多线程之间的协作)
- Android Eclipse中导入Android Design Support Library
- 69道Spring面试题和答案
- 关于java中的本地缓存-总结概述
- JAVA实现DES加密
- struts1.x国际化
- java的动态代理
- Java实现在线预览--openOffice实现