什么是ThreadLocal ?
问题引入:
线程安全的解决方案有两种加锁和创建私有变量,但加锁后任务会排队执行,消耗大量时间,每次任务会创建新的私有变量会消耗大量的资源,那么有没有一种更好的方法呢,肯定是有的啦,ThreadLocal是线程的本地变量,每一个线程会创建一个私有变量。
SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
ThreadLocal 使⽤
ThreadLocal 核⼼⽅法总共有以下三个:
- set(T):将内容存储到ThreadLocal。没有 set 操作的 ThreadLocal 容易引起脏数据。
- get:从线程中取私有变量。没有 get 操作的 ThreadLocal 对象没有意义。
- remove:从线程中移除私有变量。没有 remove 操作容易引起内存泄漏。
代码演示:
/**
* ThreadLocal使用
*/
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
//线程执行任务
Runnable runnable = new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "存入值" + threadName);
//在ThreadLocal中设置值
threadLocal.set(threadName);
//执行方法,打印线程中设置的值
print(threadName);
}
};
//创建并启动线程1
new Thread(runnable, "MyThread-1").start();
//创建并启动线程2
new Thread(runnable, "MyThread-2").start();
}
/**
* 打印线程中ThreadLocal值
*/
private static void print(String threadName) {
try{
//得到ThreadLocal中得值
String result = threadLocal.get();
//打印结果
System.out.println(threadName + "取出值" + result);
}finally {
//移除ThreadLocal中得值
threadLocal.remove();
}
}
ThreadLocal有两种初始化方法initialValue和
initialValue
⽅法(线程级别的)需要new一个变量
private static ThreadLocal<Integer> threadLocal =
new ThreadLocal() {
@Override
protected Integer initialValue() {
int num = new Random().nextInt(10);
System.out.println("执行了 initialValue 生成了:" + num);
return num;
}
};
public static void main(String[] args