一、ThreadLocal的介绍
- ThreadLocal 是 Java 中的一个类,它提供了线程局部变量的功能。线程局部变量是指每个线程拥有自己独立的变量副本,这些变量在不同的线程中互不影响。ThreadLocal 提供了一种在多线程环境下,每个线程都可以独立访问自己的变量副本的机制。
- ThreadLocal并不是一个线程,而是一个线程的局部变量
- ThreadLocal为每个线程提供单独的一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
二、ThreadLocal的使用场景
在springboot中,客户端每一次发送请求,tomcat服务器都会分配一个单独的线程,然后在这个线程上可能要执行不同的代码,比如controller、拦截器的代码啊,service的代码等等,它们都属于同一个线程。满足这个要求就可以使用ThreadLocal进行存储数据。(每一个线程都有一个单独的存储空间,那么在线程的生命周期内,我们可以共享这份存储空间)
-
ThreadLocal 在 Java 中有许多使用场景,主要用于解决以下两类问题:
-
- 线程封闭性(Thread Confinement):有些对象是非线程安全的,但是它们只在特定的线程中使用,并不被多个线程共享。使用 ThreadLocal 可以确保每个线程都有自己的对象副本,从而避免了线程安全问题。
-
- 避免传递参数(Avoid Passing Parameters):有些情况下,某个对象需要在一个方法调用链中的多个方法之间传递,但这个对象对于整个调用链来说是相同的,不应该在方法之间显式地传递。使用 ThreadLocal 可以将这个对象存储在线程局部变量中,而不必在方法参数中传递。
-
-
一些典型的 ThreadLocal 使用场景包括:
-
数据库连接管理:在多线程环境下,每个线程需要独立的数据库连接,可以使用 ThreadLocal 来管理每个线程的数据库连接,避免多个线程共享连接导致的线程安全问题。
-
会话管理:在 Web 应用中,每个用户会话通常都需要存储用户的身份信息或者其他会话相关的数据,可以使用 ThreadLocal 来存储每个用户会话的信息,确保线程安全性。
-
日志跟踪:在分布式系统中,通常需要在不同的服务之间传递某个请求的唯一标识符(例如请求ID),可以使用 ThreadLocal 来存储这个标识符,从而在整个请求处理过程中都可以方便地访问到它。
-
线程池任务参数传递:在使用线程池执行任务时,有时候需要将一些任务相关的参数传递给执行任务的线程,可以使用 ThreadLocal 来存储这些参数,而不必在任务执行时显式地传递参数。
-
-
总的来说,ThreadLocal 适合于需要在多个方法调用之间共享数据,但又不希望使用方法参数显式传递数据的情况。但需要注意,滥用 ThreadLocal 会导致内存泄漏或者其他问题,因此在使用时需要谨慎。
三、ThreadLocal的作用
- 作用:
- 要编写一个多线程安全(Thread-safe)的程序是困难的,为了
让线程共享资源
,必须小心地对共享资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意对象的锁定与释放,避免产生死结,种种因素都使得编写多线程程序变得困难。 - 尝试从另一个角度来思考多线程共享资源的问题,
既然共享资源这么困难,那么就干脆不要共享,何不为每个线程创造一个资源的复本
(创建资源复本)。将每一个线程存取数据的行为加以隔离,实现的方法就是给予每个线程一个特定空间来保管该线程所独享的资源。
- 要编写一个多线程安全(Thread-safe)的程序是困难的,为了