JAVA基础-ThreadLocal分析
来源:互联网 发布:android python kivy 编辑:程序博客网 时间:2024/05/21 08:41
ThreadLocal分析
[LOC]
ThreadLocal简介
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量。
—–百度百科
非ThreadLocal和ThreadLocal对比
非ThreadLocal
//A.javapublic class A { String name = "initvalue:"; public static void main(String[] args) { A a = new A(); Thread t1 = new Thread(new T(a)); Thread t2 = new Thread(new T(a)); t1.start(); t2.start(); }}
//T.javapublic class T implements Runnable { A a; public T(A a) { this.a =a ; } @Override public void run() { for(int i=0;i<4;i++) { a.name = a.name+i; System.out.println(Thread.currentThread().getName()+" "+a.name); } }}
运行结果如下:
Thread-0 initvalue:0
Thread-0 initvalue:01
Thread-1 initvalue:0
Thread-1 initvalue:0121
Thread-0 initvalue:012
Thread-0 initvalue:012123
Thread-1 initvalue:01212
Thread-1 initvalue:0121233
因为两个线程共享一个对象a导致了这种线程不安全的结果,大致流程如下
非hreadLocal
//A.javapublic class A { ThreadLocal<String> name = new ThreadLocal<String>(){ @Override protected String initialValue() { return "initvalue:"; }; }; public static void main(String[] args) { A a = new A(); Thread t1 = new Thread(new T(a)); Thread t2 = new Thread(new T(a)); t1.start(); t2.start(); }}
//T.javapublic class T implements Runnable { A a; public T(A a) { this.a =a ; } @Override public void run() { for(int i=0;i<4;i++) { a.name.set(a.name.get()+i); System.out.println(Thread.currentThread().getName()+" "+a.name.get()); } }}
运行结果如下:
Thread-0 initvalue:0
Thread-1 initvalue:0
Thread-0 initvalue:01
Thread-0 initvalue:012
Thread-0 initvalue:0123
Thread-1 initvalue:01
Thread-1 initvalue:012
Thread-1 initvalue:0123
流程如下:
源码分析
在调用a.name.get()的时候做了如下操作,见java\lang\ThreadLocal.java
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();}
这里通过getMap(t)获取当前线程的threadLocals该变量默认为null
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
若threadLocals为null
则调用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;}
这里调用 createMap(t, value)来创建当前线程的ThreadLocalMap变量
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }
这里将ThreadLocal变量作为key,value为值(name,”initvalue:”)保存在table[i]中
这个i是通过threadLocalHashCode来计算的
让我们来看看这个threadLocalHashCode是如何得来的
private final int threadLocalHashCode = nextHashCode(); /** * The next hash code to be given out. Updated atomically. Starts at * zero. */ private static AtomicInteger nextHashCode = new AtomicInteger(); /** * The difference between successively generated hash codes - turns * implicit sequential thread-local IDs into near-optimally spread * multiplicative hash values for power-of-two-sized tables. */ private static final int HASH_INCREMENT = 0x61c88647;
threadLocalHashCode使用过静态变量nextHashCode计算得来的
也就是说每个ThreadLocal变量的nextHashCode值都是不一样的
我们再来看看上面的get()方法
if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } }
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
这里也是通过该变量的threadLocalHashCode来获取变量存储的位置并返回变量的
这样整个流程就理通了
下面展示了ThreadLocal的草图
- JAVA基础-ThreadLocal分析
- Java基础之ThreadLocal
- Java基础 之ThreadLocal
- Java基础 ThreadLocal
- Java基础之ThreadLocal
- 【Java基础】理解ThreadLocal
- java基础-ThreadLocal学习
- Java基础----ThreadLocal
- Java中ThreadLocal分析
- java-----ThreadLocal源码分析
- Java ThreadLocal源码分析
- 《Java源码分析》:ThreadLocal /ThreadLocalMap
- java 1.8 ThreadLocal源码分析
- Java 并发 ---ThreadLocal源码分析
- 不惑JAVA之JAVA基础 - ThreadLocal
- java基础—Java里面的Threadlocal
- java中ThreadLocal技术原理分析
- 【Java并发编程实践】— ThreadLocal分析
- TSBanitnemelEtsellamShtK.230
- 树莓派spi液晶屏支持(fbtft)nt35510
- 将数组中负数调到正数之前,但相对位置不变
- Spark中组件Mllib的学习11之使用ALS对movieLens中一百万条(1M)数据集进行训练,并对输入的新用户数据进行电影推荐
- Mybatis学习——关联表查询
- JAVA基础-ThreadLocal分析
- 输出最高最低分
- UVA - 1605 Building for UN (思路题)
- Mysql GTID主从复制
- Design Patterns for User Interface for Mobile Applications
- Scala支持与Java的隐式转换
- 一看就懂的设计模式(一,简单工厂模式)
- JavaScript DOM 中获取元素属性
- 字符串比较