ThreadLocal 原理

57 阅读1分钟

什么是TheadLocal

ThreadLocal 是 Java 里一种特殊变量,它是一个线程级别变量,每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞态条件被彻底消除了,在并发模式下是绝对安全的变量。

下面通过例子了解一下ThreadLocal:

    /**
     * ThreadLocal变量,每个线程都有一个副本,互不干扰
     */
    public static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();

    public static void main(String[] args) throws Exception {
        new ThreadLocalDemo().threadLocalTest();
    }

    public void threadLocalTest() throws Exception {
        // 主线程设置值
        THREAD_LOCAL.set("wupx");
        String v = THREAD_LOCAL.get();
        System.out.println("Thread-0线程执行之前," + Thread.currentThread().getName() + "线程取到的值:" + v);

        new Thread(new Runnable() {
            @Override
            public void run() {
                String v = THREAD_LOCAL.get();
                System.out.println(Thread.currentThread().getName() + "线程取到的值:" + v);
                // 设置 threadLocal
                THREAD_LOCAL.set("huxy");
                v = THREAD_LOCAL.get();
                System.out.println("重新设置之后," + Thread.currentThread().getName() + "线程取到的值为:" + v);
                System.out.println(Thread.currentThread().getName() + "线程执行结束");
            }
        }).start();
        // 等待所有线程执行结束
        Thread.sleep(3000L);
        v = THREAD_LOCAL.get();
        System.out.println("Thread-0线程执行之后," + Thread.currentThread().getName() + "线程取到的值:" + v);
    }
}

这是运行结果: Thread-0线程执行之前,main线程取到的值:wupx Thread-0线程取到的值:null 重新设置之后Thread-0线程取到的值为:huxy Thread-0线程执行结束 Thread-0线程执行之后,main线程取到的值:wupx

ThreadLocal 内存泄露

ThreadLocal在没有外部引用时,发生GC时会被回收,那么ThreadLocalMap中保存的key值就变成了null,而Entry又被threadLocalMap对象引用,threadLocalMap对象又被Thread对象所引用,如果当前Thread运行时间很长的话,例如Thread存活于线程池中,value对象就会一直存在于内存中,就可能会导致内存泄露,直至Thread被销毁后,才会被回收。