深入理解Java中的ThreadLocal

深入理解Java中的ThreadLocal

转自:

http://www.java265.com/JavaCourse/202205/3370.html

下文笔者讲述java中ThreadLocal的详解说明,如下所示:

ThreadLocal简介

ThreadLocal的功能:
   用于创建线程局部变量的类
----------------------------------------------------------------------------
我们都知道我们创建的变量,可以被任何一个线程访问和修改
但是当我们使用ThreadLocal创建的变量只能被当前线程访问,其他线程无法访问和修改
-----------------------------------------------------------------------------

ThreaLocal用法示例

ThreadLocal定义:
   ThreadLocal<String> threadLocalInfo = new ThreadLocal<>();

set方法 
   threadLocalInfo.set("java265.com");
get方法
   threadLocalInfo.get();

完整的示例
 private void testThreadLocal() {
    Thread t = new Thread() {
        ThreadLocal<String> threadLocalInfo = new ThreadLocal<>();

        @Override
        public void run() {
            super.run();
            threadLocalInfo.set("java265.com--我最爱的网站");
            threadLocalInfo.get();
        }
    };

    t.start();
}

ThreadLocal初始值–设置方法

ThreadLocal设置默认的get初始值
  需要重写initialValue方法

例:
ThreadLocal<String> mThreadLocal = new ThreadLocal<String>() {
    @Override
    protected String initialValue() {
      return Thread.currentThread().getName();
    }
};

ThreadLocal的set方法原理说明

 
set方法源码:
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
} 

getMap: 

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

class Thread implements Runnable {
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

当一开始设置,即ThreadLocalMap对象未创建
则新建ThreadLocalMap对象,并设置初始值
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

ThreadLocal导致内存泄露的原因说明

  ThreadLocal实例被线程的ThreadLocalMap实例持有,也可以看成被线程持有。
  当我们使用了线程池,由于之前的线程实例处理完之后出于复用的目的依然存活
  即ThreadLocal设定的值被持有,才会导致内存泄露 
  ThreadLocal并不会产生内存泄露
  因为ThreadLocalMap在选择key的时候
  并不是直接选择ThreadLocal实例
   而是ThreadLocal实例的弱引用。

static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object).  Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table.  Such entries are referred to
* as "stale entries" in the code that follows.
*/
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
}

ThreadLocal使用场景

 如:tractional 
    一个数据库连接,在一个线程中只此一份,所以可使用ThreadLocal实现线程间变量共享
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 深入理解Java中的ThreadLocal