ThreadLocal模式的纵向隔离与横向隔离

《struts2技术内幕》中说到了TheadLocal模式的纵向隔离与横向隔离问题,这里写细一些帮助记忆


图1


如上图每个thread中都有一个ThreadLocalMap变量,并且其中以各个ThreadLocal实例为key存着变量。

这样thread之间即为同一threadlocal类不同实例的纵向隔离。

一个thread内ThreadLocalMap根据不同ThreadLocal得到相应变量值即为横向隔离。


具体到后面的例子代码如下:

public class Counter {
	
// 新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象
    private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>() {
	 protected synchronized Integer initialValue() {
	         return 10;
	 }
};
	
// 通过静态的get方法访问ThreadLocal中存储的值
public static Integer get() {
	return counterContext.get();
}
	
// 通过静态的set方法将变量值设置到ThreadLocal中
public static void set(Integer value) {
	counterContext.set(value);
}
	
// 封装业务逻辑,操作存储于ThreadLocal中的变量
public static Integer getNextCounter() {
    counterContext.set(counterContext.get() + 1);
    return counterContext.get();
}
    
}
虽然Count中counterContext是类变量,然而在执行getNextCounter()时,threadlocal的set方法已经获得当前线程对象,并且得到线程对象中的ThreadLocalMap,将自己与要保存的值存成了图1的结构。

public class ThreadLocal<T> {

// 这里省略了许多其他代码

// 将value的值保存于当前线程的本地变量中
public void set(T value) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 调用getMap方法获得当前线程中的本地变量ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    // 如果ThreadLocalMap已存在,直接使用
    if (map != null)
         // 以当前的ThreadLocal的实例作为key,存储于当前线程的
         // ThreadLocalMap中,如果当前线程中被定义了多个不同的ThreadLocal
         // 的实例,则它们会作为不同key进行存储而不会互相干扰
         map.set(this, value);
    else
         // ThreadLocalMap不存在,则为当前线程创建一个新的
         createMap(t, value);
}

 // 获取当前线程中以当前ThreadLocal实例为key的变量值
public T get() {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 获取当前线程中的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 获取当前线程中以当前ThreadLocal实例为key的变量值
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    // 当map不存在时,设置初始值
    return setInitialValue();
}

// 从当前线程中获取与之对应的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

 // 创建当前线程中的ThreadLocalMap
void createMap(Thread t, T firstValue) {
    // 调用构造函数生成当前线程中的ThreadLocalMap
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

// ThreadLoaclMap的定义
static class ThreadLocalMap {
    // 这里省略了许多代码
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocal提供了一种以空间换时间的方式,为每个线程提供了一份变量的副本,从而实现了线程间的数据隔离。每个Thread对象都有一个ThreadLocalMap成员变量,用于存储线程的局部变量副本。每个线程在访问ThreadLocal变量时,实际上是通过ThreadLocalMap来获取副本数据。ThreadLocalMap中的key是ThreadLocal实例的弱引用,value是对应的局部变量副本。由于key是弱引用,当ThreadLocal实例被回收时,对应的局部变量副本也会被回收,从而实现了对ThreadLocal的回收。通过ThreadLocal实现的数据隔离能够让多个线程并发执行而不会相互干扰,同时解决了哈希冲突问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ThreadLocal 线程隔离](https://blog.csdn.net/weixin_49561445/article/details/120597228)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [java ThreadLocal(应用场景及使用方式及原理)](https://blog.csdn.net/weixin_34128501/article/details/86245024)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值