公正廉明的 ThreadLocal

ThreadLocal

在移动端开发中很少会使用到这个类,首先来说明一下,该类是干什么的。

在多线程环境下用来保证,线程变量不会被其他线程可见,当前线程独享。

那么我们通过一个故事来说明一下。

假设我们每一个人都是一个线程。而ThreadLocal是一个打柜子的师傅。

你刚出生的时候,也就是 线程刚被 new 出来的时候,这个时候呢,你手里面已经有了一个可以打柜子的地方,但是这个地方是没有实体柜子的也就是空的(null),也是就是每一个线程里面都会有一个ThreadLocalMap对象的引用,这个地方好好体会一下,是不是很形象。

有一天你觉得这个地方如果不放上柜子的话,太浪费了,在现在这个寸土寸金的年代,不行我要打上柜子才行,有点私人物品需要放在里面,那么这个时候你就找到了 号称 java 界的鲁班大师,ThreadLocal  先生。

你:先生我想要打一个柜子。

TL:没有问题,我的手艺跟鲁班大师有的一比。

TL:您是打一个新的柜子,还是说原来有柜子了,找我来换把锁就行。

你:我需要新做一个,有些私人东西,需要放在里面。不能被其他人看见才行。

TL:您放心,我在钥匙在 ,我丢钥匙也不能丢。

TL:哒哒哒干了一上午,一个漂亮的柜子终于完工了。

你:谢谢师傅。我要把我的,所有金银首饰都放在里面,还用袋子给装一下,(就是 ThreadLocalMap 中的 value 都是用弱引用,包装起来的),这样他们就不会丢了。

TL:我的柜子放的是君子,但是如果真的有小人看上你的东西的话,我可能会发现不了。

大师的这句话,的意思就是在说明,ThreadLocal 会产生,内存泄露。到底是怎么产生的呢。

有一天你不在家,大师也正在晒太阳,家里面来个小偷,他并没有把柜子给抬走,而是在柜子下面转了一个孔,把你的财宝都给卷走了,但是呢柜子从外面看上去一点事情都没有发生过一样,谁能知道里面的东西没有了。

GC 就是那个小偷。GC 在扫描的时候,把弱引用包裹的对象全部都标记上可回收了,那么GC在处理这些对象的时候,直接就会清除掉,但是呢 只是value 被清理了,key依然完好,就是柜门依然完好,只是内容丢了,从外面看没有任何问题,这个不就是浪费了,柜子的地方吗,程序中不就是内存泄露了吗,所以为了防止这样的情况产生,在用完的时候记得删除数据。

ThreadLocal 是顶级大师,肯定找他干事情的人比较多,有好的也有坏的,有想自己打柜子的,也有想看看别人的柜子里面装的是什么的,那么对于想看看别人柜子了装的是什么的人,大师也就一句话,“滚” ,我可能世界顶级大师,公正廉明是我的座右铭,你不要坏了我的名声。

下面一个简单的小示例,演示了一下,顶级大师 是怎么叫坏人“滚”的

 /**
     * 这个就是打柜子的师傅
     */
    static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        /**
         * 这个表示的是打柜子。当前柜子是在主线程打的。
         * 是主线程专属的柜子,使用权只能是主线程,别的线程
         * 是不可能拿到的
         */
        threadLocal.set("zhang");

        new Thread() {
            @Override
            public void run() {
                // 别的线程把打柜子的师傅给请了过去,想要拿,柜子里面的东西。
                // 那对不起,师傅是不会容许这么干的。柜子只能是自己用自己的
                // 你要使用的话,我给你打一个自己的柜子,你想装什么都可以
                threadLocal.set("lisi");
                String string = threadLocal.get();
                System.out.println(string);
            }
        }.start();


    }

在自己的一亩三分地,打柜子

  /**
     * 这个就是打柜子的师傅
     */
    static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        /**
         * 这个表示的是打柜子。当前柜子是在主线程打的。
         * 是主线程专属的柜子,使用权只能是主线程,别的线程
         * 是不可能拿到的
         */
        threadLocal.set("zhang");

        new Thread() {
            @Override
            public void run() {
                // 别的线程把打柜子的师傅给请了过去,想要拿,柜子里面的东西。
                // 那对不起,师傅是不会容许这么干的。柜子只能是自己用自己的
                // 你要使用的话,我给你打一个自己的柜子,你想装什么都可以
                threadLocal.set("lisi");
                String string = threadLocal.get();
                System.out.println(string);
            }
        }.start();


    }

这样自己有了柜子,放自己的东西,就行了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值