`

ThreadLocal源码学习

    博客分类:
  • Java
阅读更多

ThreadLocal,线程本地化对象,在多线程环境中,使用ThreadLocal对象来维护变量时,ThreadLocal为每个使用该变量的线程维护一个独立的线程副本。

ThreadLocal.java源文件内容为:

/**
  * ThreadLocal内部包含一个用数组实现的哈希表,用来存储对应到每个线程的局部对象的值
  * 其中,ThreadLocal对象担当key,实际通过threadLocalHashCode值来进行检索
  */
public class ThreadLocal<T> {
	//其中 T 类型代表的是被多个线程访问的局部变量类型 
	/** 
	* 在ThreadLocalMaps中用于产生哈希值 
	*/ 
	private final int threadLocalHashCode = nextHashCode(); 
	/** 
	* Returns the current thread's "initial value" for this 
	* thread-local variable. This method will be invoked the first 
	* time a thread accesses the variable with the {@link #get} 
	* method, unless the thread previously invoked the {@link #set} 
	* method, in which case the <tt>initialValue</tt> method will not 
	* be invoked for the thread. Normally, this method is invoked at 
	* most once per thread, but it may be invoked again in case of 
	* subsequent invocations of {@link #remove} followed by {@link #get}. 
	* * <p>This implementation simply returns <tt>null</tt>; if the 
	* programmer desires thread-local variables to have an initial 
	* value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be 
	* subclassed, and this method overridden. Typically, an 
	* anonymous inner class will be used. 
	* * @return the initial value for this thread-local(返回当前线程局部对象的初始值) 
	*/ 
	protected T initialValue() { 
		//protected成员,期望被子类继承 
		return null; 
	} 
	/** 
	* 返回在当前线程中的线程局部对象的值, 
	* 若线程局部对象对于当前线程没有值,则被初始化微 initialValue方法的返回值 
	*/ 
	public T get() { 
		Thread t = Thread.currentThread(); 
		ThreadLocalMap map = getMap(t); 
		if (map != null) { 
			ThreadLocalMap.Entry e = map.getEntry(this); 
			if (e != null) 
				return (T)e.value; 
		} 

			return setInitialValue(); 
	} 

	/** 
	* Sets the current thread's copy of this thread-local variable 
	* to the specified value. Most subclasses will have no need to 
	* override this method, relying solely on the method to set the values of thread-locals. 
	*/ 
	public void set(T value) { 
		Thread t = Thread.currentThread(); 
		ThreadLocalMap map = getMap(t); 
		if (map != null) 
			//以当前线程对象为key,设置当前局部对象的值
			map.set(this, value); 
		else 
			createMap(t, value); 
	} 

	/** 
	* Removes the current thread's value for this thread-local 
	* variable. If this thread-local variable is subsequently 
	* {@linkplain #get read} by the current thread, its value will be 
	* reinitialized by invoking its {@link #initialValue} method, 
	* unless its value is {@linkplain #set set} by the current thread 
	* in the interim. This may result in multiple invocations of the 
	* <tt>initialValue</tt> method in the current thread. 
	*/ 
	public void remove() { 
		ThreadLocalMap m = getMap(Thread.currentThread()); 
		if (m != null) 
			//从ThreadLocalMap中移除对象
			m.remove(this); 
	} 

	/** 
	* Get the map associated with a ThreadLocal. Overridden in 
	* InheritableThreadLocal. 
	* * @param t the current thread 
	* @return the map 
	*/ 
	ThreadLocalMap getMap(Thread t) { 
		//返回当前Threadlocal相关的ThreadLocalMap对象 
		return t.threadLocals; 
	} 

	/** 
	* Create the map associated with a ThreadLocal. Overridden in 
	* InheritableThreadLocal. 
	* * @param t the current thread 
	* @param firstValue value for the initial entry of the map 
	* @param map the map to store. 
	*/ 
	void createMap(Thread t, T firstValue) { 
		t.threadLocals = new ThreadLocalMap(this, firstValue); //为当前线程创建关联的ThreadLocalMap对象 
	} 

	//ThreadLocalMap是一个定制的只能用来存储线程局部对象的哈希映射 
	//使用弱引用来当做key,只有当表空间不够时,旧的对象才会被移除 
	static class ThreadLocalMap { 
		//ThreadLocalMap的内部数组的元素类型:使用对ThreadLocal的弱引用类型来作为元素类型 
		static class Entry extends WeakReference<ThreadLocal> { 
		/** 
		* The value associated with this ThreadLocal. 
		*/ 
		Object value; 

		Entry(ThreadLocal k, Object v) { 
			super(k); 
			value = v; 
		} 
	} 

	//哈希表的初始大小 
	private static final int INITIAL_CAPACITY = 16; 

	/** 
	* 用于存储ThreadLocal弱引用的数组 
	*/ 
	private Entry[] table; 

	//ThreadLocalMap使用延迟初始化,当我们需要向ThreadLocalMap中放元素时,才会初始化它 
	ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { 
		table = new Entry[INITIAL_CAPACITY]; 
		int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); 
		table[i] = new Entry(firstKey, firstValue); //初始时,使用ThreadLocal.threadLocalHashCode作为哈希表的哈希值 size = 1; 

		//设定ThreadLocalMap中元素个数 
		setThreshold(INITIAL_CAPACITY); 
	} 

	/** 
	* Set the value associated with key. 
	* * @param key the thread local object 
	* @param value the value to be set 
	*/ 
	private void set(ThreadLocal key, Object value) { 
		// We don't use a fast path as with get() because it is at 
		// least as common to use set() to create new entries as 
		// it is to replace existing ones, in which case, a fast 
		// path would fail more often than not. 
		Entry[] tab = table; 
		int len = tab.length; 
		int i = key.threadLocalHashCode & (len-1); 
		for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { 
			ThreadLocal k = e.get(); 
			if (k == key) { 
				e.value = value; 
				return; 
			} 

			if (k == null) { 
				replaceStaleEntry(key, value, i); 
				return;
			} 
		} 

		tab[i] = new Entry(key, value); 
		int sz = ++size; 
		if (!cleanSomeSlots(i, sz) && sz >= threshold) 
			rehash(); 
	} 

	/** 
	* Remove the entry for key. 
	*/ 
	private void remove(ThreadLocal key) { 
		Entry[] tab = table; 
		int len = tab.length; 
		int i = key.threadLocalHashCode & (len-1); 
		for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { 
			if (e.get() == key) { 
				e.clear(); 
				expungeStaleEntry(i); 
				return; 
			} 
		} 
	} 
}

 

 ThreadLocal使用一个ThreadLocalMap对象(内部通过数组和哈希来保存,以当前线程为键)来为每一个线程保存一份变量的本地化对象。

分享到:
评论

相关推荐

    Java并发编程学习之ThreadLocal源码详析

    Java并发编程学习之ThreadLocal源码详析 ThreadLocal是Java并发编程中的一种机制,用于解决多线程访问共享变量的问题。它可以使每个线程对共享变量的访问都是线程安全的,使得多线程编程变得更加简单。 ...

    threadLocal

    源码分析: 在Java的`ThreadLocal`实现中,每个线程都有一个`ThreadLocalMap`,它是`ThreadLocal`的一个内部类,用于存储线程局部变量。`ThreadLocalMap`使用弱引用作为键,目的是在线程不再引用ThreadLocal对象时,...

    Spring事务处理-ThreadLocal的使用

    通过深入源码学习,我们可以更好地理解Spring如何在多线程环境中优雅地管理事务,以及如何利用ThreadLocal来优化并发性能。同时,了解数据库连接池的工作原理也有助于我们更好地配置和使用连接池,提升应用程序的...

    从ThreadLocal的使用到Spring的事务管理

    在IT行业中,线程安全和事务管理是两个非常重要的概念,尤其在多线程环境下的分布式系统中。本文将深入探讨ThreadLocal的使用以及...通过深入学习源码和实际应用,我们可以更好地理解其工作原理,并在实践中灵活运用。

    深入学习java ThreadLocal的源码知识

    理解ThreadLocal的原理和源码对于开发高并发的Java应用至关重要,因为它可以帮助我们正确地管理线程状态,保证程序的稳定性和性能。在使用ThreadLocal时,注意及时清理不再使用的ThreadLocal实例,以防止内存资源的...

    javajdk源码学习-JavaSourceLearn:JDK源码学习

    jdk源码学习 JavaSourceLearn 版本号 版本 corretto-1.8.0_275 方式 逐步阅读源码添加注释、notes文件夹添加笔记 计划学习任务计划 标题为包名,后面序号为优先级1-4,优先级递减 java.lang Object 1 String 1 ...

    Java相关技术的源码学习心得

    在深入探讨Java源码学习心得之前,我们先要理解Java作为一种多用途、面向对象的编程语言,其广泛应用于企业级应用、移动应用、云计算、大数据等领域。Java的源码是理解其工作原理的关键,这对于提升编程技能、解决...

    Hibernager_Session_Manager_ThreadLocal

    标题“Hibernage_Session_Manager_ThreadLocal”涉及到的是Hibernate框架中的一种优化策略——使用ThreadLocal管理Session。...理解这些知识点对于深入学习Hibernate和优化Java Web应用的数据库操作至关重要。

    32个经典程序设置源码.rar

    "32个经典程序设置源码.rar"这个压缩包显然包含了一系列与编程相关的示例代码,旨在帮助开发者理解和学习如何实现特定的功能。以下是根据标题、描述以及标签所涉及到的一些关键知识点的详细说明: 1. **创建椭圆形...

    JDK10(JDK10底层C++源码及hotspot虚拟机源码)

    **JDK10与OpenJDK10源码解析** ...总的来说,探索JDK10的C++源码和HotSpot虚拟机源码是一次极具价值的学习过程,能够提升开发者在Java平台上的专业技能,为优化代码、调试问题以及实现高性能应用提供有力的支持。

    java8源码-jdk8-source:jdk8-源代码

    Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...

    java8源码-java8-source-code:Java8API源代码

    Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...

    Java大师级源码-Java8-Source-Code-master:jdk1.8源码,无注释版本

    Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...

    应用源码之MessageManager.zip

    总结,MessageManager是Android开发中实现线程间通信的重要工具,它的源码学习有助于我们掌握Android的消息处理机制。通过深入分析MessageManager的实现,我们可以提升在并发编程和UI更新方面的技能,更好地应对复杂...

    java源码笔记

    - 设计模式:学习Java源码中常见的设计模式,如单例、工厂、观察者等,提升代码质量。 - 内存模型:理解JVM内存结构,如堆、栈、方法区,以及垃圾回收机制。 6. **并发编程** - 线程安全:synchronized、...

    《Java Concurrency in Practice》源码

    通过对《Java Concurrency in Practice》的源码进行学习和分析,我们可以深入理解Java并发编程的核心原理,提升在实际项目中处理并发问题的能力。同时,这也有助于我们更好地利用Java提供的并发工具和框架,编写出...

    基于SpringBoot+Mybatis+Redis开发的一个问答社区源码+sql数据库(仿牛客网).zip

    使用 ThreadLocal 保存用户状态,通过拦截器拦截请求,根据自定义注解判断用户登录状态 使用 Ajax 异步发帖、发送私信、评论 使用 Redis 实现点赞、关注功能,优化登录模块——存储登录凭证、缓存用户信息 【备注】 ...

    java8源码-ac_babel:一些后端学习笔记整理

    源码 设计模式 java 并发 public class Foo { // SimpleDateFormat is not thread-safe, so give one to each thread private static final ThreadLocal formatter = new ThreadLocal(){ @Override protected ...

    JUC并发编程与源码分析视频课.zip

    8. **线程局部变量**:学习ThreadLocal类的使用,了解如何在多线程环境中维护线程局部状态。 9. **锁的高级特性**:包括读写锁(ReentrantReadWriteLock)、乐观锁(StampedLock)以及锁的可重入性、公平性和非公平...

    疯狂Java实战演义【书+源码】(疯狂Java讲义课后习题项目)

    总的来说,《疯狂Java实战演义》结合源码为读者提供了一条全面学习Java编程的道路,从基础到高级,从理论到实践,帮助读者成为Java开发的高手。通过阅读和实践书中的项目,读者可以不断提升自己的编程技能,并且能够...

Global site tag (gtag.js) - Google Analytics