ThreadLocal--线程局部变量

写在本文之前:

多线程的初衷是通过使用多个Thread来充分利用CPU资源,并发的完成任务。

多线程的难点就在于如何处理多个线程共享同一资源这一问题。(显而易见不是吗? 如果多个线程互不相干,还有什么需要你费神呢)

因此,concurrency包下的大部分内容、或者说我们所关心的并发问题,一定是应用在这种场景之下的:从宏观上共享的访问同一资源。

即如下图所示,

133513_mPsV_947997.png

这里留一个问题先:

thread1、thread2如何拿到Main thread中source的引用?

你可能会说,在创建thread1/2的时候通过参数传引用。这是个办法;

However,如果thread1中方法调用很深,最底层的方法需要操作source,难道我需要在invocation chain中的每一层传递source的引用?

说到这里,你应该猜到了,ThreadLocal的用途之一:可以用来避免在thread中传递参数。


作用:

ThreadLocal又叫线程局部变量

如果一个变量声明为ThreadLocal类型, 那么每一个与之关联(经过此处)的Thread 都被允许持有一份(当前thread独享的)该ThreadLocal变量的value。

通俗点讲,对于ThreadLocal类型的变量,每一个线程都有一个属于他自己的value,线程之间互不影响。

从效果上来看,ThreadLocal实现的效果和Synchronized实现的效果(多个线程共享同一变量)正好相反。


应用场景

1. 避免线程内部invocation chain中的参数传递(参见文章开始的问题)。

2. 在线程内部持有对象引用;这个线程内部的对象引用对其他线程是不可见的,并且不同的线程持有的对象名称相同(e.g. 在Web应用的server side, 管理所有session的场景中,就可以使用ThreadLocal将session按照用户登录Thread存储起来)


API:

ThreadLocal.get()

ThreadLocal.set(T t)

ThreadLcoal.initialValue()

e.g.

public class DemoThread extends Thread{
    private static String defaultUser = "defaultUser";
    private static String defaultPwd = "defaultPwd";
    private static ThreadLocal<User> threadUser = new ThreadLocal<>(){
        @Override
        protected User initialValue(){
            User defaultUser = new User(defaultUser, defaultPwd);
            return defaultUser;
        }
    };
    ...
    public void run(){
        if(useDefault){
            User user = new User(userName, pwd);
            threadUser.set(user);
        }
        ...
        User currentUser = threadUser.get();
    }
}


JDK实现:

Thread类中有一个属性 threadLocals, 包含了当前Thread所有ThreadLocal变量的值。

    public class Thread implements Runnable{
        ....
        /* ThreadLocal values pertaining to this thread. This map is maintained
         * by the ThreadLocal class. */
        ThreadLocal.ThreadLocalMap threadLocals = null;
        ....
    }

以ThreadLocal静态对象为map key,当前Thread关于此ThreadLocal的值为map的value。

    public class ThreadLocal<T>{
        ...
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = t.threadLocals;
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null)
                    return (T)e.value;
            }
            return setInitialValue();
        }
   }




转载于:https://my.oschina.net/mose/blog/669597

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值