juc之ThreadLocal

并发工具类——分类

juc之ThreadLocal

ThreadLocal

使用场景

juc之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");
        }
    };

juc之ThreadLocal

典型场景2: 使用set在ThreadLocal中存入全局变量,在其他方法中使用get读取,避免参数传递

ThreadLocal的两个作用

juc之ThreadLocal

ThreadLocal的好处

juc之ThreadLocal
juc之ThreadLocal

原理

juc之ThreadLocal
juc之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

juc之ThreadLocaljuc之ThreadLocal

void set(T t) 和 T get()

juc之ThreadLocal

void remove()

juc之ThreadLocal

ThreadLocal注意点

内存泄露

juc之ThreadLocal
juc之ThreadLocal
juc之ThreadLocal
juc之ThreadLocal

空指针异常

juc之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://www.icode9.com/i/ll/?i=20210708juc之ThreadLocal
juc之ThreadLocal

实际应用场景

juc之ThreadLocal

上一篇:c# AsyncLocal ThreadLocal ExecutionContext


下一篇:ThreadLocal的原理及产生的问题