ThreadLocal
该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。
线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式
ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属于当前线程,即保证每个线程的变量不一样,而同一个线程在任何地方拿到的变量都是一致的,这就是所谓的线程隔离。
ThreadLocal被称为线程局部变量,就相当于把数据存储于线程本地,取也是在本地内存读取,就不会像synchronized需要频繁的修改主内存的数据,再把数据复制到工作内存,也大大提高访问效率。
作用:
threadlocal用于存取线程独享数据,提高访问效率
举例
1 public class Demo { 2 3 private ThreadLocal<Integer> count = new ThreadLocal<Integer>(){ 4 @Override 5 protected Integer initialValue() { 6 return new Integer(0); 7 } 8 }; 9 10 public int getNext(){ 11 Integer value = count.get(); 12 value++; 13 count.set(value); 14 return value; 15 } 16 17 public static void main(String[] args) { 18 Demo d =new Demo(); 19 20 new Thread(new Runnable() { 21 @Override 22 public void run() { 23 while (true){ 24 System.out.println(Thread.currentThread().getName()+" "+d.getNext()); 25 try { 26 Thread.sleep(1000); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 } 31 } 32 }).start(); 33 34 new Thread(new Runnable() { 35 @Override 36 public void run() { 37 while (true){ 38 System.out.println(Thread.currentThread().getName()+" "+d.getNext()); 39 try { 40 Thread.sleep(1000); 41 } catch (InterruptedException e) { 42 e.printStackTrace(); 43 } 44 } 45 } 46 }).start(); 47 48 new Thread(new Runnable() { 49 @Override 50 public void run() { 51 while (true){ 52 System.out.println(Thread.currentThread().getName()+" "+d.getNext()); 53 try { 54 Thread.sleep(1000); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 } 59 } 60 }).start(); 61 62 } 63 64 }
Console()
Thread-0 1
Thread-1 1
Thread-2 1
Thread-0 2
Thread-1 2
Thread-2 2
。。。。。。
源码分析:
get(),set(),remove()
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(); }
Thread.currentThread()拿到当前线程绑定
值最终存储到了 ThreadLocalMap 下的 Entry 的 value 里
如果 ThreadLocalMap 为空,return setInitialValue()
private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }
调用 initialValue() 方法 ,默认返回空,
拿到当前线程,ThreadLocalMap ,getMap()
如果map不等于空,就把当前值设置进去,map为空,就创建map
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
ThreadLocalMap map = getMap(t);
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
当前线程的ThreadLocals,ThreadLocalMap 是 ThreadLocal 里引用的实例
获取时给线程绑定上threadLocals
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap是ThreadLocal的静态内部类
静态类中引入静态类 Entry
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
ThreadLocal<?> 为key Object 作为值
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); }
remove
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
获取到ThreadLocalMap.不为空,直接移除。
完