最近工作涉到系统的Sass改造,我们采取的方法便是:动态的切换数据库,中间使用到ThreadLocal,以前对它并不熟悉,这里进行学习,记录下。
什么是ThreadLocal
看看官方文档怎么说。
ThreadLocal
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
该类提供线程本地变量。这些变量与普通的对应变量不同之处在于,每个访问一个线程(通过其get或set方法)都有自己的、独立初始化的变量副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
image.png我的理解:
每个线程都有自己独立的变量副本,ThreadLocal作为一个容器,存在当前线程与当前线程的变量副本,而且当前线程可以在当前线程中拿到自己的变量副本,也只能拿到自己变量副本,也就保证的变量副本之间的线程隔离。
有不正确的地方,还希望大家指出。
ThreadLocal 的中主要方法
- public T get() {...}
返回当前线程的变量副本,如果不存在,则通过initialValue()方法生成。 - protected T initialValue() {...}
返回当前线程变量副本初始值。 - public void remove() {...}
移除当前线程的变量副本. - public void set(T value) {...}
设置当前线程的变量副本。
如果大家想进一步了解,可以查看ThreadLocal的源码。
ThreadLocal源码分析:https://blog.csdn.net/sonny543/article/details/51336457
ThreadLocal 例子
- example 1 返回当前线程独一无二的线程id 官方例子
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}
测试代码
@Test
public void test() {
System.out.println(ThreadId.get());
System.out.println(ThreadId.get());
System.out.println(ThreadId.get());
new Thread(() -> {
System.out.println(ThreadId.get());
System.out.println(ThreadId.get());
System.out.println(ThreadId.get());
}).start();
}
返回结果
image.png
- example 2 DateFormat 工具类
阿里巴巴 java 开发手册中推荐的 ThreadLocal 的用法
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class DateUtil {
public static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
}
@Test
public void test2() {
System.out.println(DateUtil.df.get().format(new Date()));
System.out.println(DateUtil.df.get().format(new Date()));
System.out.println(DateUtil.df.get().format(new Date()));
}
返回结果
image.png
网友评论