真实项目中 ThreadLocal 的妙用

2019-10-21  本文已影响0人  人生如茶几

一、什么是ThreadLocal

ThreadLocal提供了线程的局部变量,每个线程都可以通过set()和get()来对这个局部变量进行操作,但不会和其他线程的局部变量冲突,实现了线程间的数据隔离

简单讲:一个获取用户的请求线程A,如果向TheadLocal填充变量A value(只能被线程A操作),该变量对其他获取用户的请求B、C …是隔离的。

最简单的使用方式:

类似一次HTTP请求线程重,利用ThreadLocal存储Cookie对象,进行状态管理。setCookie:

上面存储格式是String,实际场景存储的是具体的对象,在这次HTTP请求过程中,任何时候都可以获取Cookie。获取方式很简单getCookie:

二、熟悉的场景

    2.1 数据库连接池

        比如一次请求线程进来,业务Dao需要更新user表和user-detail表。如果是new出两个数据库Connection,分别部用的Connection操作User表和user-detail表,就无法保证事务。那么数据库连接池是如何保证的?

       答案是:利用ThreadLocal存储唯一Connection对象。每次请求线程,pool.getConnection获取链接的时候都会这样操作:

       a  会从ThreadLocal获取Connection对象。如果有,则保证了后面多个数据库作共用同一个Connection,从而保证了事务。

      b  如果没有,往ThreadLocal新增Connection对象,并返回到线程。

         因为conn是线程不安全的。这样会导致多个请求公用一个链接。请求量很大的情况下,延迟各种。

因此,使用ThreadLocal保证每个请求线程的Connection是唯一的。即每个线程有自己的链接。

        继续讲到Spring框架,在事务开始时,会给当前线程一个jdbc Connection,在整个事务过程,都时使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就时用的ThreadLocal来实现这种隔离

        2.2 HTTP Cookie

        比如你访问百度、我访问百度,会有不同Cookie。而且你不能访问我的Cookie,我也不能。顾名思义,使用ThreadLocal保证每个HTTP请求线程的Cookie是唯一。

        Cookie这样才能做Session等状态管理

三 实战场景

            总结一下就是:ThreadLocal可以让同一个线程中上下文之间数据共享 

        简单的例子:

            适用满足这两个条件的场景:1、每个线程独有的一些信息,2、这些信息又会在多个方法或类中用到

            1、一个请求线程,里面有两个异步小线程,各有一个方法,分别处理A或B业务

            2、一种方法是传递不可变的入参

            3、另一种就是TheadLocal,放在TheadLocal的入参,会被各个方法共享。而且多个请求线程互不影响

        复杂的例子:

            一次发货操作:会根据入参,进行组件化、流程编排话。那么入参会被各个地方用到,而且有些流程组件是异步的(类似new thread操作的)。这时候可以定一个XXContext上下文:

        代码解析:

               都是static操作,类似DateUtil玩法

                  记得每次请求线程后清理。可以AOP去清理,加个注解就行。因为同一个请求线程可能被也业务方公用。

上一篇 下一篇

猜你喜欢

热点阅读