美文网首页
简单易懂Java 并发-ThreadLocal原理

简单易懂Java 并发-ThreadLocal原理

作者: DoubleFooker | 来源:发表于2019-10-11 10:45 被阅读0次

ThreadLocal的作用

当在多线程环境下,每个线程都可以对共享变量进行操作,如果我们希望每个线程都有专属于自己的变量,不被其他线程影响,那么我们可以使用ThreadLocal实现专属于线程的副本变量。例如常见的SimpleDateFormat是线程不安全的,而我们又不希望每次使用都创建一个,那么我们可用使用ThreadLocal封装

  private static final ThreadLocal<SimpleDateFormat> FORMAT_THREAD_LOCAL = ThreadLocal
            .withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    countDownLatch.await();
                    SimpleDateFormat simpleDateFormat = FORMAT_THREAD_LOCAL.get();
                    Date now = new Date();
                    String format = simpleDateFormat.format(now);
                    System.out.println(Thread.currentThread().getName() + ":before:" + format);
                    // 修改只对当前线程有效
                    FORMAT_THREAD_LOCAL.set(new SimpleDateFormat("yyyy-MM-dd"));
                    System.out.println(Thread.currentThread().getName() + ":after:" +FORMAT_THREAD_LOCAL.get().format(now));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "Thread" + i).start();
        }
        countDownLatch.countDown();
    }

ThreadLocal原理

先看下Thread类的属性

class Thread implements Runnable {
    //类似map,key-value关联
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

ThreadLocal#get方法

    public T get() {
        Thread t = Thread.currentThread();
        // 获取线程的Map,threadLocals 
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                // 从map中返回值
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        // 初始化map
        return setInitialValue();
    }
  private T setInitialValue() {
        // 初始化构建方法。jdk8支持withInitial创建
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //保存值,关联当前线程,key为当前线程
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

ThreadLocal通过管理当前线程的ThreadLocalMap实现变量的线程隔离,每个线程只都保存自己的副本,ThreadLocal提供中间人的作用,供调用者获取线程的本地值。

相关文章

网友评论

      本文标题:简单易懂Java 并发-ThreadLocal原理

      本文链接:https://www.haomeiwen.com/subject/yjglpctx.html