ThreadLocal简介
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:
因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这也是 ThreadLocal 命名的由来。
既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。
ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。
总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。
ThreadLocal与Synchronized的区别
ThreadLocal其实是与线程绑定的一个变量。ThreadLocal和Synchonized都用于解决多线程并发访问。
但是ThreadLocal与synchronized有本质的区别:
1、Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
2、Synchronized是利用锁的机制,使变量或代码块在某一时刻只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
一句话理解ThreadLocal,threadlocal是作为当前线程中属性ThreadLocalMap集合中的某一个Entry的key值Entry(threadlocal,value),虽然不同的线程之间threadlocal这个key值是一样,但是不同的线程所拥有的ThreadLocalMap是独一无二的,也就是不同的线程间同一个ThreadLocal(key)对应存储的值(value)不一样,从而到达了线程间变量隔离的目的,但是在同一个线程中这个value变量地址是一样的。
使用步骤
使用ThreadLocal的基本步骤如下:
1、创建一个ThreadLocal对象:可以通过ThreadLocal的静态工厂方法ThreadLocal.withInitial()来创建。
2、在需要使用线程私有变量的地方,通过get()方法获取当前线程的变量副本。
3、在当前线程中设置变量的值,可以使用set()方法来设置。
4、使用完毕后,及时清理资源,可以通过remove()方法来清除当前线程的变量副本。
应用场景
使用ThreadLocal可以解决多线程并发访问时的线程安全问题,常见的应用场景包括:
1、线程上下文信息的传递:通过ThreadLocal可以在多个方法之间传递线程上下文信息,避免显式地传递参数。
2、数据库连接管理:使用ThreadLocal可以确保每个线程都拥有自己的数据库连接,避免线程间的资源竞争和冲突。
3、全局变量的线程安全访问:将全局变量封装在ThreadLocal中,每个线程都可以独立地访问自己的副本,避免线程安全问题。
简单的代码示例
public class ThreadLocalExample {
private static ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "Initial Value");
public static void main(String[] args) {
// 在主线程中设置变量值
threadLocal.set("Main Thread Value");
// 创建两个子线程并启动
Thread thread1 = new Thread(() -> {
// 获取并打印变量值
System.out.println("Thread 1: " + threadLocal.get());
// 设置新的变量值
threadLocal.set("Thread 1 Value");
// 打印新的变量值
System.out.println("Thread 1: " + threadLocal.get());
});
Thread thread2 = new Thread(() -> {
// 获取并打印变量值
System.out.println("Thread 2: " + threadLocal.get());
// 设置新的变量值
threadLocal.set("Thread 2 Value");
// 打印新的变量值
System.out.println("Thread 2: " + threadLocal.get());
});
thread1.start();
thread2.start();
// 打印主线程的变量值
System.out.println("Main Thread: " + threadLocal.get());
// 清除主线程的变量副本
threadLocal.remove();
}
}
在上述示例中,我们创建了一个ThreadLocal
对象threadLocal
,并在主线程中设置了变量的初始值。然后,创建了两个子线程,并在每个子线程中获取和设置变量的值。最后,在主线程中打印了变量的值,并清除了主线程的变量副本。
需要注意的是,ThreadLocal
并不能解决多线程共享资源的线程安全问题,它仅提供了一种线程私有变量的机制。在使用ThreadLocal
时,应注意及时清理资源,避免内存泄漏。
参考链接:https://blog.csdn.net/u010445301/article/details/111322569