ThreadLcoal不是线程,而是一个创建线程的局部变量的类,主要用于存储多线程下类的某些变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,当前线程的ThreadLocal的变量只能被该线程访问,而其他线程访问不到。
使用 类定义,支持泛型public class ThreadLocal<T>
初始化值private T setInitialValue()
set方法public void set(T value)
get方法public T get()
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class Test04 { private ThreadLocal<Integer> local = new ThreadLocal <>(); int i=0 ; class localTread implements Runnable { public void setNum () { local.set(i++); } public Integer getNum () { return local.get(); } @Override public void run () { if (local.get() == null ){ setNum(); System.out.println("set threadlocal num..." ); } System.out.print("the object is: " ); System.out.println(local); System.out.println(local.get()); } } public static void main (String[] args) { try { localTread t = new Test04 ().new localTread (); Thread t1 = new Thread (t); Thread t2 = new Thread (t); Thread t3 = new Thread (t); t1.start(); Thread.sleep(1000 ); t2.start(); Thread.sleep(1000 ); t3.start(); } catch (InterruptedException e) { e.printStackTrace(); } } }
输出
1 2 3 4 5 6 7 8 9 set threadlocal num... the object is: java.lang.ThreadLocal@6b2ce86d 0 set threadlocal num... the object is: java.lang.ThreadLocal@6b2ce86d 1 set threadlocal num... the object is: java.lang.ThreadLocal@6b2ce86d 2
可以看到三个线程访问的都是同一个ThreadLocal,但只能访问当前线程存储的各自的变量。 看源码set方法的实现
1 2 3 4 5 6 7 8 public void set (T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null ) map.set(this , value); else createMap(t, value); }
通过获取当前线程,再ThreadL中,ThreadLocalMap用弱引用实现 get方法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 public T get () { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null ) { ThreadLocalMap.Entry e = map.getEntry(this ); if (e != null ) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
同样是为了解决多线程中变量冲突的问题,线程同步机制实现在某个时间点只有一个线程能访问变量,而ThreadLcoal是通过存储每个线程自己变量,以隔离多线程访问数据的冲突,一个损耗时间,一个损耗空间。