ThreadLocal类的使用

  线程之间的共享变量可以通过public static变量的形式实现,如果要实现每一个线程都有自己私有的变量,最简单的方法就是为每一个启动的线程初始化一个线程实例
  一个线程对应一个线程实例,如以下代码所示:

class MyThread extends Thread{
    public  String test;
    MyThread(String val){
        this.test=val;
    }

    @Override
    public void run(){
        System.out.println("线程——"+Thread.currentThread().getName()+"变量arg的值是:"+test);
    }

    public static void main(String[] args) {
        new MyThread("A").start();
        new MyThread("B").start();
        new MyThread("C").start();
    }
}

  输出结果:

线程——Thread-0变量test的值是:A
线程——Thread-2变量test的值是:C
线程——Thread-1变量test的值是:B

  比一个线程创建一个线程实例更灵活的方法就是使用ThreadLocal类,实现线程之间的变量隔离。
  ThreadLocal类的使用如以下代码所示:

class MyThreadLocalTest extends Thread{
    public static ThreadLocal<String>local=new ThreadLocal<>();
    @Override
    public void run(){
        local.set(Thread.currentThread().getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程——"+Thread.currentThread().getName()+"变量local的值是:"+local.get());
    }

    public static void main(String[] args) {
        MyThreadLocalTest test=new MyThreadLocalTest();
        new Thread(test,"A").start();
        new Thread(test,"B").start();
        new Thread(test,"C").start();
    }
}

  输出结果:

线程——C变量local的值是:C
线程——B变量local的值是:B
线程——A变量local的值是:A

  虽然A、B、C三个线程使用的是同一个线程实例,并且对变量local都进行了赋值,但输出的结果表示三个线程的local变量的值各不相同,并没有发生值覆盖,所以三个线程的local变量是相互隔离的,不是共享变量。也就是说ThreadLocal类实现了线程之间的变量隔离。
  那么ThreadLocal类对于线程之间变量隔离的实现原理是什么呢?
  每个Thread实例中都会有一个ThreadLocalMap对象threadLocals,其中存储的是键值对,键值对的存储格式为为“ThreadLocal实例 —> Value”。
ThreadLocal类的使用

  当调用ThreadLocal变量local的set方法时,方法内部会通过Thread.currentThread获取当前线程,再从当前线程中获取ThreadLocalMap,往ThreadLocalMap中存储键值,健就是当前的ThreadLocal变量local,值就是set(val)的参数val。
  当我们要获取ThreadLocal变量对所对应的值时,同理,获取到当前线程的ThreadLocalMap对象,在该map中获取ThreadLocal变量local对应的value即可。这就是ThreadLocal中get方法的原理。
  ThreadLocal存储结构如下图所示:

ThreadLocal类的使用

上一篇:ThreadLocal


下一篇:深入分析 ThreadLocal 内存泄漏问题