目录
  • Threadlocal有什么用:
  • ThreadLocal使用实例
    • API介绍
    • ThreadLocal的使用
  • Threadlocal 的源码分析
    • 原理
    • 源码
  • 内部类ThreadLocalMap
    • ThreadLocalMap存储位置
      • Key的弱引用问题
        • java中的四种引用
          • 总结:

            Threadlocal有什么用:

            简单的说就是,一个ThreadLocal在一个线程中是共享的,在不同线程之间又是隔离的(每个线程都只能看到自己线程的值)。如下图:

            Java 超详细讲解ThreadLocal类的使用

            ThreadLocal使用实例

            API介绍

            在使用Threadlocal之前我们先看以下它的API:

            Java 超详细讲解ThreadLocal类的使用

            ThreadLocal类的API非常的简单,在这里比较重要的就是get()、set()、remove(),set用于赋值操作,get用于获取变量的值,remove就是删除当前变量的值.需要注意的是initialValue方法会在第一次调用时被触发,用于初始化当前变量值,默认情况下initialValue返回的是null。

            ThreadLocal的使用

            说完了ThreadLocal类的API了,那我们就来动手实践一下了,来理解前面的那句话:一个ThreadLocal在一个线程中是共享的,在不同线程之间又是隔离的(每个线程都只能看到自己线程的值)

            public class ThreadLocalTest {
            
                private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
            	// 重写这个方法,可以修改“线程变量”的初始值,默认是null
                    @Override
                    protected Integer initialValue() {
                        return 0;
                    }
                };
            
                public static void main(String[] args) throws InterruptedException {
            
                    //一号线程
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("一号线程set前:" + threadLocal.get());
                            threadLocal.set(1);
                            System.out.println("一号线程set后:" + threadLocal.get());
                        }
                    }).start();
            
                    //二号线程
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("二号线程set前:" + threadLocal.get());
                            threadLocal.set(2);
                            System.out.println("二号线程set后:" + threadLocal.get());
            
                        }
                    }).start();
            
                    //主线程睡1s
                    Thread.sleep(1000);
            
                    //主线程
                    System.out.println("主线程的threadlocal值:" + threadLocal.get());
            
                }
            
            }
            
            

            稍微解释一下上面的代码:

            每一个ThreadLocal实例就类似于一个变量名,不同的ThreadLocal实例就是不同的变量名,它们内部会存有一个值(暂时这么理解)在后面的描述中所说的“ThreadLocal变量或者是线程变量”代表的就是ThreadLocal类的实例。

            在类中创建了一个静态的 “ThreadLocal变量”,在主线程中创建两个线程,在这两个线程中分别设置ThreadLocal变量为1和2。然后等待一号和二号线程执行完毕后,在主线程中查看ThreadLocal变量的值。

            程序结果及分析⌛

            Java 超详细讲解ThreadLocal类的使用

            程序结果重点看的是主线程输出的是0,如果是一个普通变量,在一号线程和二号线程中将普通变量设置为1和2,那么在一二号线程执行完毕后在打印这个变量,输出的值肯定是1或者2(到底输出哪一个由操作系统的线程调度逻辑有关)。但使用ThreadLocal变量通过两个线程赋值后,在主线程程中输出的却是初始值0。在这也就是为什么“一个ThreadLocal在一个线程中是共享的,在不同线程之间又是隔离的”,每个线程都只能看到自己线程的值,这也就是 ThreadLocal的核心作用:实现线程范围的局部变量。

            Threadlocal 的源码分析

            原理

            每个Thread对象都有一个ThreadLocalMap,当创建一个ThreadLocal的时候,就会将该ThreadLocal对象添加到该Map中,其中键就是ThreadLocal,值可以是任意类型。 这句话刚看可能不是很懂,下面我们一起看完源码就明白了。

            前面我们的理解是所有的常量值或者是引用类型的引用都是保存在ThreadLocal实例中的,但实际上不是的,这种说法只是让我们更好的理解ThreadLocal变量这个概念。向ThreadLocal存入一个值,实际上是向当前线程对象中的ThreadLocalMap存入值,ThreadLocalMap我们可以简单的理解成一个Map,而向这个Map存值的key就是ThreadLocal实例本身。

            源码

            Java 超详细讲解ThreadLocal类的使用

            声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。