虽然这个不是标准的数据结构,但是在java中还是挺重要的结构类。所以需要好好了解一下
该类的使用非常简单,大概就下面的两个操作。
static final ThreadLocal<T> sThreadLocal = new ThreadLocal<T>();
sThreadLocal.set()
sThreadLocal.get()
sThreadLocal.remove()
ThreadLocal存在一个静态内部类ThreadLocalMap。当调用set的时候,首先获取当前线程对象t。然后线程t中存在一个成员变量threadLocals (指向ThreadLocal的静态内部类ThreadLocalMap),默认为null。 //如果存在ThreadLocalMap就直接set,没有则创建ThreadLocalMap并set。 然后将ThreadLocal对象作为key,用户的值作为value值。放入map中。

其实具体是采用ThreadLocal的threadLocalHashCode属性作为key。该属性是被final修饰的int不可变属性。所以可以唯一确定一个ThreadLocal对象。
  但是如何保证两个同时实例化的ThreadLocal对象有不同的threadLocalHashCode属性:在ThreadLocal类中,还包含了一个static修饰的AtomicInteger([??t?m?k]提供原子操作的Integer类)成员变量(即类变量)和一个static final修饰的常量(作为两个相邻nextHashCode的差值)。由于nextHashCode是类变量,所以每一次调用ThreadLocal类都可以保证nextHashCode被更新到新的值,并且下一次调用ThreadLocal类这个被更新的值仍然可用,同时AtomicInteger保证了nextHashCode自增的原子性。
总的来说其原理主要是通过为每个Thread 维护一个属于自己的map。然后通过不同的ThreadLocal对象作为key来存取不同的value值。也就是说再多线程环境中,对于同一个ThreadLocal对象,当处于不同的线程中时,对应的value值是不一样的。因为线程不一样->map不一样。
package ztext;
/**
 * @author xgj
 */
public class MyTest {
        ThreadLocal<Long> longLocal = new ThreadLocal<>();
        ThreadLocal<String> stringLocal = new ThreadLocal<>();
        Long along = Long.valueOf(1000);
        public void set() {
            along+=100;
            longLocal.set(along);
            stringLocal.set(Thread.currentThread().getName());
        }
        public long getLong() {
            return longLocal.get();
        }
        public String getString() {
            return stringLocal.get();
        }
        public static void main(String[] args) throws InterruptedException {
            final MyTest test = new MyTest();
            test.set();
            System.out.println(test.getLong());
            System.out.println(test.getString());
            Thread thread1 = new Thread(() -> {
                test.set();
                System.out.println(test.getLong());
                System.out.println(test.getString());
            });
            Thread thread2 = new Thread(() -> {
                test.set();
                System.out.println(test.getLong());
                System.out.println(test.getString());
            });
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
        }
}
的运行结果如下:

也就是说对于共有变量Long,并没有起到隔离作用
如果改为:
package ztext;
/**
 * @author xgj
 */
public class MyTest {
        ThreadLocal<Long> longLocal = new ThreadLocal<>();
        ThreadLocal<String> stringLocal = new ThreadLocal<>();
        Long along = Long.valueOf(1000);
        public void set() {
            Long  blong = along+100;
            longLocal.set(blong);
            stringLocal.set(Thread.currentThread().getName());
        }
        public long getLong() {
            return longLocal.get();
        }
        public String getString() {
            return stringLocal.get();
        }
        public static void main(String[] args) throws InterruptedException {
            final MyTest test = new MyTest();
            test.set();
            System.out.println(test.getLong());
            System.out.println(test.getString());
            Thread thread1 = new Thread(() -> {
                test.set();
                System.out.println(test.getLong());
                System.out.println(test.getString());
            });
            Thread thread2 = new Thread(() -> {
                test.set();
                System.out.println(test.getLong());
                System.out.println(test.getString());
            });
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
        }
}
结果:


初始容量16,负载因子2/3,解决冲突的方法是再hash法,
原文:https://www.cnblogs.com/jiezao/p/13678520.html