【JAVA基础-多线程】- ThreadLocal

最近工作涉到系统的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 官方例子
public class MainDemo {

    private static final AtomicInteger atomicInteger = new AtomicInteger(0);

    private static final ThreadLocal threadId = new ThreadLocal() {
        @Override
        protected Integer initialValue() {
            return atomicInteger.getAndIncrement();
        }
    };
    // 简化写法
    private static final ThreadLocal threadId2 = ThreadLocal.withInitial(() -> atomicInteger.getAndIncrement());

    public static int get() {
        return threadId.get();
    }

    public static void main(String[] args) {
        System.out.println(get()); // 0

        new Thread(() -> System.out.println(threadId.get())).start(); // 1

        new Thread(() -> System.out.println(threadId.get())).start(); // 2
    }
}

返回结果


image.png
  • example 2 DateFormat 工具类
    阿里巴巴 java 开发手册中推荐的 ThreadLocal 的用法
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class DateUtil {
    public static final ThreadLocal df = new ThreadLocal() {
        @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

参考文献:https://www.xttblog.com/?p=3087

你可能感兴趣的:(【JAVA基础-多线程】- ThreadLocal)