ThreadLocal的入门代码实践及使用和实现原理

 

为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个 Thread ,而是 Thread 的局部变量。

查看Thread 源码可得知:

 /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

ThreadLocal 原理:每个线程的内部都维护了一个 ThreadLocalMap,它是一个 Map(key,value)数据格式,key 是一个弱引用,也就是 ThreadLocal 本身,而 value 存的是线程变量的值。

直接运行一段代码

/**
 * 36ThreadLocal 使用及实现原理
 * 
Thread-0  1
Thread-1  1
Thread-2  1

Thread-0  2
Thread-1  2
Thread-2  2

Thread-1  3
Thread-0  3
Thread-2  3
 * @author Administrator
 */
public class Demo38ThreadLocal {
	private ThreadLocal<Integer> count = new ThreadLocal<Integer>(){
		@Override
		protected Integer initialValue() {
			return new Integer(0);
		}
	};

	public int getNext() {
		Integer value = count.get();
		value++;
		count.set(value);
		return value;
	}

	public static void main(String[] args) {
		Demo38ThreadLocal demo = new Demo38ThreadLocal();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+ demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+ demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
}

       

 线程资源持有

线程独立资源持有是threadlocal最常用的使用方式,比如从单线程应用扩展到多线程应用。

 线程资源一致性 

  

Entry数组的长度为啥一定要是2的幂

  

Hash 冲突

ThreadLocalMap 中解决 Hash 冲突的方式并非链表的方式,而是采用线性探测的方式.

所谓线性探测,就是根据初始 key 的 hashcode 值确定元素在 table 数组中的位置,如果发现这个位置上已经被其他的 key 值占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。

 

ThreadLocal特性

ThreadLocal和Synchronized都是为了解决多线程中相同变量的访问冲突问题,不同的点是

  • Synchronized是通过线程等待,牺牲时间来解决访问冲突
  • ThreadLocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突,并且相比于Synchronized,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值。

内存泄漏

ThreadLocal 应用场景 

  • 线程间数据隔离,各线程的 ThreadLocal 互不影响
  • 方便同一个线程使用某一对象,避免不必要的参数传递
  • 全链路追踪中的 traceId 或者流程引擎中上下文的传递一般采用 ThreadLocal
  • Spring 事务管理器采用了 ThreadLocal
  • Spring MVC 的 RequestContextHolder 的实现使用了 ThreadLocal

 

 

ThreadLocal问了父子线程怎么共享数据 interitableThreadLocals

https://blog.csdn.net/hewenbo111/article/details/80487252?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

InheritableThreadLocal与阿里的TransmittableThreadLocal设计思路解析

https://blog.csdn.net/u010833547/article/details/99647118?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章