真实项目中 ThreadLocal 的妙用

  • 时间:
  • 浏览:0
  • 来源:3分时时彩官网_3分时时彩投注平台注册_3分时时彩下注平台注册

一、什么是 ThreadLocal

ThreadLocal 提供了多多线程 运行的局部变量,每个多多线程 运行都还不用 通过 set() 和 get() 来对你这一 局部变量进行操作,但不用和有些多多线程 运行的局部变量冲突,实现了多多线程 运行间的据隔离。

简单讲:另另一个获取用户的请求多多线程 运行 A,机会向 ThreadLocal 填充变量 AValue(还不用 了被多多线程 运行 A 操作),该变量对有些获取用户的请求多多线程 运行 B、C...是隔离的.

最简单的使用最好的法律土办法:

这一 一次 HTTP 请求多多线程 运行中,利用 ThreadLocal 存储 Cookie 对象,进行状况管理。set Cookie:

private ThreadLocal httpThreadLocal = new ThreadLocal();

httpThreadLocal.set(“Cookie: sid=13420771402233”)

底下存储格式是 String ,实际场景存储的是具体的对象。在这次 HTTP 请求过程中,任何事先都还不用 获取 Cookie 。获取最好的法律土办法很简单 get Cookie:

String cookieValue = (String) httpThreadLocal.get();

Thread 与 ThreadLocal 对象引用关系图

二、你熟悉的场景

2.1 数据库连接池

比如一次请求多多线程 运行进来,业务 Dao 都要更新 user 表和 user-detail 表。机会是 new 出另另一个数据库 Connection ,分别不同的 Connection 操作 user 表和 user-detail 表,就无法保证事务。如此数据库连接池是如保保证的?

答案是:利用 ThreadLocal 存储唯一 Connection 对象。每次请求多多线程 运行,pool.getConnection 获取连接的事先就有什么都有我操作:

  • 会从 ThreadLocal 获取 Connection 对象。机会有,则保证了底下多个数据库操作共用同另另一个 Connection ,从而保证了事务。
  • 机会如此,往 ThreadLocal 新增Connection 对象,并返回到多多线程 运行
错误的做法
public class XXXService {

    private Connection conn;
}

机会 conn 是多多线程 运行不安全的。什么都有我会导致 多个请求公用另另一个连接。请求量很大的状况下,延迟各种。你懂。

如保让,使用 ThreadLocal 保证每个请求多多线程 运行的 Connection 是唯一的。即每个多多线程 运行有我本人的连接。

继续讲到 Spring 框架,在事务已经 开始时,会给当前多多线程 运行另另一个Jdbc Connection,在整个事务过程,就有使用该多多线程 运行绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架底下什么都有我用的ThreadLocal来实现你这一 隔离

比如你访问百度、我访问百度,会有不同 Cookie 。如保已经 还不用 了访问我的 Cookie,我什么都有我能。顾名思义,使用 ThreadLocal 保证每个 HTTP 请求多多线程 运行的 Cookie 是唯一的。

Cookie 什么都有我不用 做 Session 等状况管理。

三、实战场景

总结一下什么都有我:ThreadLocal 还不用 让同另另一个多多线程 运行中上下文之间数据共享

在底下章节 二、你熟悉的场景 觉得介绍了什么都有现有场景。如此我这边具体的实战场景是什么?

简单的例子:

适用满足这另另一个条件的场景:1.每个多多线程 运行独有的有些信息,2.什么信息又会在多个最好的法律土办法或类中用到。

  1. 另另一个请求多多线程 运行,底下有另另一个异步小多多线程 运行,各有另另一个最好的法律土办法。分别处里 A 或 B 业务
  2. 一种生活生活最好的法律土办法是传递不可变的入参
  3. 另一种生活生活什么都有我 ThreadLocal,放上去去 ThreadLocal 的入参,会被各个最好的法律土办法共享。如保让多个请求多多线程 运行互不影响
僵化 的例子:

一次发货操作:会根据入参,进行组件化、流程编排话。如此入参会被各个地方用到,如保让有些流程组件是异步的(这一 new thread 操作的)。这事先还不用 定另另一个 XXContext 上下文:

public class XXContext {
    
    private static ThreadLocal<Map<Class<?>, Object>> context = new InheritableThreadLocal<>();
    
    /**
     * 把参数设置到上下文的Map中
     */
    public static void put(Object obj) {
        Map<Class<?>, Object> map = context.get();
        if (map == null) {
            map = new HashMap<>();
            context.set(map);
        }
        if (obj instanceof Enum) {
            map.put(obj.getClass().getSuperclass(), obj);
        } else {
            map.put(obj.getClass(), obj);
        }
    }
    
    /**
     * 从上下文中,根据类名取出参数
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(Class<T> c) {
        Map<Class<?>, Object> map = context.get();
        if (map == null) {
            return null;
        }
        return (T) map.get(c);
    }
    
    /**
     * 清空ThreadLocal的数据
     */
    public static void clean() {
        context.remove();
    }
}

代码解析:

  • 就有 static 操作,这一 DateUtil 玩法
  • 记得每次请求多多线程 运行后清理。还不用 AOP 去清理,加个注解就行。机会同另另一个请求多多线程 运行机会被业务方公用。

(完)