并发工具类——分类
ThreadLocal
使用场景
典型场景1:初始化ThreadLocal,使得不安全的工具类线程安全
public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal
= ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
典型场景2: 使用set在ThreadLocal中存入全局变量,在其他方法中使用get读取,避免参数传递
ThreadLocal的两个作用
ThreadLocal的好处
原理
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;ThreadLocalMap
}
}
return setInitialValue();
}
- 每个线程都有一个对应的ThreadLocalMap,在get方法中先获取当前线程对应的ThreadLocalMap,ThreadLocalMap中的键值对是当前的ThreadLocalMap和对应的内容,所以可以通过map.getEntry(this)获取对应的内容。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
- set方法与get方法相反
主要方法介绍
initialValue
void set(T t) 和 T get()
void remove()
ThreadLocal注意点
内存泄露
空指针异常
public class Main {
public static void main(String[] args) {
System.out.println(ThreadLocalUtil.get());
}
}
class ThreadLocalUtil {
public static ThreadLocal<Long> longThreadLocal = new ThreadLocal<>();
public static void set(Long num) {
longThreadLocal.set(num);
}
public static long get() {
return longThreadLocal.get();
}
public static void remove() {
longThreadLocal.remove();共享对象
}
}
以上代码会导致空指针异常,而不会输出null,这是因为get方法返回时进行了拆箱,无法对null进行拆箱,导致空指针异常。
其他注意点
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210708