ThreadLocal实现

1.用法	<开发艺术>P376代码
	private ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<Boolean>();
	...
	mBooleanThreadLocal.set(true);
	mBooleanThreadLocal.get();
	...
	new Thread() {
		public void run() {
			mBooleanThreadLocal.set(false);
			sys(mBooleanThreadLocal.get());
		}
	}
	综上:
		入口1:new ThreadLocal<Boolean>()
		入口2:mBooleanThreadLocal.set(false);
		入口3:mBooleanThreadLocal.get();

2.根据入口分析源代码:
	2.1 入口1:new ThreadLocal<Boolean>()
	ThreadLocal.java
	public ThreadLocal() {}
	
	2.2 入口2:mBooleanThreadLocal.set(false);
	public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread); // 第一次调用values都是空
        if (values == null) {
            values = initializeValues(currentThread);	
        }
        values.put(this, value);	// this:ThreadLocal对象
    }
	
		Values values(Thread current) {
			// Thread.java中定义 ThreadLocal.Values localValues; //Normal thread local values.
			return current.localValues; 
		}
		
		Values initializeValues(Thread current) {
			return current.localValues = new Values();
		}
	
			// Values类(内部类)
			// Values类内部使用数组(类似哈希表)保存键值对(key:ThreadLocal value:T泛型)
			/**
			 * Per-thread map of ThreadLocal instances to values. 线程map
			 */
			static class Values {
				/**
				 * Map entries. Contains alternating keys (ThreadLocal) and values.
				 */
				private Object[] table;
					
				/**
				 * Sets entry for given ThreadLocal to given value, creating an
				 * entry if necessary.
				 */
				void put(ThreadLocal<?> key, Object value) {

					// Keep track of first tombstone. That's where we want to go back
					// and add an entry if necessary.
					int firstTombstone = -1;

					for (int index = key.hash & mask;; index = next(index)) {
						Object k = table[index];

						if (k == key.reference) {	// 修改已有key的值 
							// Replace existing entry.
							table[index + 1] = value;
							return;
						}

						if (k == null) {
							if (firstTombstone == -1) {
								// Fill in null slot.
								table[index] = key.reference;	// 第一个索引存key,接下去一个索引存value
								table[index + 1] = value;
								size++;
								return;
							}

							// Go back and replace first tombstone.
							table[firstTombstone] = key.reference;
							table[firstTombstone + 1] = value;
							tombstones--;
							size++;
							return;
						}
						...
					}
				}	

				private int next(int index) {
					return (index + 2) & mask;
				}				
			}
			
	2.3 入口3:mBooleanThreadLocal.get();
	public T get() {
        // Optimized for the fast path.
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values != null) {	
            Object[] table = values.table;	// 本质调用:Values类中成员/方法
            int index = hash & values.mask;
            if (this.reference == table[index]) {	// 之前有put数据
                return (T) table[index + 1];
            }
        } else {
            values = initializeValues(currentThread);	// 未put数据
        }

        return (T) values.getAfterMiss(this);	// 还未put的时候:返回null
    }		
	
3.总结:
	3.1 整个过程涉及到三个类:ThreadLocal类,Thread类(内部有成员Values),Values类(ThreadLocal类的内部类)
		每个Thread类内部都有一个Values成员,而Values成员包含键值对(ThreadLocal, T泛型数据)
		对ThreadLocal类的put和get操作本质是操作对应线程的Values成员变量键值对(ThreadLocal, T泛型数据)
		多个线程可以保存同一个ThreadLocal对象的引用,但是对应的值是副本形式,而不是共同的引用
	3.2 
		入口2:mBooleanThreadLocal.set(false); // ThreadLocal类
			ThreadLocal的set方法只做一些错误和简单逻辑判断,真正维护键值对(ThreadLocal,T泛型)和set操作是在Values类(核心)
		入口3:mBooleanThreadLocal.get();	// ThreadLocal类
			ThreadLocal的get方法只做一些错误和简单逻辑判断,真正维护键值对(ThreadLocal,T泛型)和get操作是在Values类(核心)
			Values类从已经保存的Object[]数组中找到之前set操作存入的键值对,并返回key对应的value
		
4.思考:如果自己会如何实现?
	自己实现:ThreadLocal类内部维护一个Map,key:thread value:T(真正的数据).这样put的时候根据线程和value存成一个键值对
	源码实现:每个Thread中自己维护一个Values变量(ThreadLocal类的内部类),put的时候,把ThreadLocal引用和真正数据保存到Thread对应的
		成员变量Values(可以看做维护一个Map,key:ThreadLocal value:真正数据),这样Values成员就能保存对个Item(key:ThreadLocal value:真正数据)	
	
	
	
	
	
	
	
	
	
	
	





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值