我们来详细讲解一下“Java多线程之ThreadLocal原理总结”的完整攻略。
1. 什么是ThreadLocal
ThreadLocal 是 Java 提供的一种本地线程变量,可以为每个线程存储一份独立的变量副本,各自互不影响。这样可以避免多个线程之间对同一个变量进行竞争锁,增加程序的运行效率。
2. ThreadLocal 实现原理
ThreadLocal 实现原理非常简单:在ThreadLocal的内部实现中,通过一个ThreadLocalMap来存储每个线程单独的数据,ThreadLocalMap中存储的是以ThreadLocal对象为键,以线程本地变量为值的数据。
其中,ThreadLocalMap 的 key 是弱引用,value 是普通引用。当线程结束时,ThreadLocalMap 中的键值对会被自动清除。
3. ThreadLocal 示例演示
以下是一个简单的示例,通过 ThreadLocal 实现线程局部变量,并在一个线程里面进行数据的读取和修改。
public class ThreadLocalDemo {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
@Override
public Integer initialValue() {
return 0;
}
};
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
//获取当前线程的线程局部变量的值
int before = threadLocal.get();
System.out.println("线程1开始时,threadLocal存储的值:" + before);
//设置当前线程的线程局部变量的值
threadLocal.set(100);
//获取当前线程的线程局部变量的值
int after = threadLocal.get();
System.out.println("线程1结束时,threadLocal存储的值:" + after);
});
Thread thread2 = new Thread(() -> {
//获取当前线程的线程局部变量的值
int before = threadLocal.get();
System.out.println("线程2开始时,threadLocal存储的值:" + before);
//设置当前线程的线程局部变量的值
threadLocal.set(200);
//获取当前线程的线程局部变量的值
int after = threadLocal.get();
System.out.println("线程2结束时,threadLocal存储的值:" + after);
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
上述示例中通过 ThreadLocal 为每个线程存储一个局部变量,通过 initialValue() 方法设置初始值,然后在线程内对局部变量进行读取和修改。
输出结果如下:
线程1开始时,threadLocal存储的值:0
线程2开始时,threadLocal存储的值:0
线程1结束时,threadLocal存储的值:100
线程2结束时,threadLocal存储的值:200
可以发现,每个线程都有一个独立的局部变量,互不干扰。
4. ThreadLocal 使用场景
ThreadLocal 可以用于需要手动管理资源、线程安全的类。例如连接池、时间格式化等,可以将这些资源以 ThreadLocal 的形式存储在每个线程中,实现自动管理。
下面是一个使用 ThreadLocal 管理时间格式化的示例:
public class DateFormatter {
private static final ThreadLocal<SimpleDateFormat> dateFormatHolder =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static String format(Date date) {
return dateFormatHolder.get().format(date);
}
public static void main(String[] args) {
Date date = new Date();
System.out.println("当前时间:" + DateFormatter.format(date));
}
}
输出结果如下:
当前时间:2022-07-04 15:36:06
可以看到,dateFormatHolder 在每个线程中都有一份独立的副本,不会互相干扰,实现了线程安全,同时也不需要手动管理线程安全,简化了代码实现。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之ThreadLocal原理总结 - Python技术站