Java ThreadLocal 类

来源:互联网 发布:网吧系统还原软件 编辑:程序博客网 时间:2024/05/08 00:38

一个例子(参考自张孝祥老师的视频)

代码

package com.jue.test_thread_local;import java.util.Random;public class TestMain {private static ThreadLocal<Integer> tl = new ThreadLocal<Integer>();public static void main(String[] args) {TestMain tm = new TestMain();tm.test();}public void test() {for (int i = 0; i < 3; i++) {new Thread() {@Overridepublic void run() {int data = new Random().nextInt(200);tl.set(data);System.out.println(Thread.currentThread().getName() + " thread data = " + data);new A().testA();}}.start();}}static class A {public void testA() {System.out.println("A -> testA() " + Thread.currentThread().getName() + " thread data " + tl.get());}}}

结果

TestMain-> test Thread-1 thread data = 199TestMain-> test Thread-2 thread data = 16TestMain-> test Thread-0 thread data = 55A->testA() Thread-2 thread data 16A->testA() Thread-1 thread data 199A->testA() Thread-0 thread data 55

每个线程一个单例的实现

ThreadSingleton

public class ThreadSingleton {private String threadName;private static ThreadLocal<ThreadSingleton> sThreadLocal = new ThreadLocal<ThreadSingleton>();private ThreadSingleton(String name) {threadName = name;}public static ThreadSingleton getInstance() {if (sThreadLocal.get() == null) {String name = Thread.currentThread().getName();sThreadLocal.set(new ThreadSingleton(name));}return sThreadLocal.get();}@Overridepublic String toString() {return "ThreadSingleton, threadName = " + threadName + " #" + this.hashCode();}}

注意:getInstance方法不需要加synchronized同步锁

TestMain

public class TestMain {public static void main(String args[]) {for (int i = 0; i < 5; i++) {new Thread() {@Overridepublic void run() {ThreadSingleton ts1 = ThreadSingleton.getInstance();ThreadSingleton ts2 = ThreadSingleton.getInstance();System.out.println(ts1);System.out.println(ts2);}}.start();}}}

输出结果

ThreadSingleton, threadName = Thread-2 #1024915921ThreadSingleton, threadName = Thread-2 #1024915921ThreadSingleton, threadName = Thread-3 #2121724417ThreadSingleton, threadName = Thread-3 #2121724417ThreadSingleton, threadName = Thread-0 #1647036297ThreadSingleton, threadName = Thread-0 #1647036297ThreadSingleton, threadName = Thread-1 #113690433ThreadSingleton, threadName = Thread-4 #185211847ThreadSingleton, threadName = Thread-1 #113690433ThreadSingleton, threadName = Thread-4 #185211847

源码分析

字段

    private final int threadLocalHashCode = nextHashCode();

记录当前hashCode值

方法

返回下一个hashCode

    /**     * Returns the next hash code.     */    private static int nextHashCode() {        return nextHashCode.getAndAdd(HASH_INCREMENT);    }

返回当前线程存储的 thread-local variable

    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)方法,发现访问的是Thread类的threadLocals字段

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

查看Thread类发现下面的字段,即:thread-local variable 是因为thread对象的间接持有

    ThreadLocal.ThreadLocalMap threadLocals = null;

设置当前线程的thread -local variable

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

移除当前线程的thread-local variable

     public void remove() {         ThreadLocalMap m = getMap(Thread.currentThread());         if (m != null)             m.remove(this);     }

静态内部类ThreadLocalMap

静态内部类Entry

        static class Entry extends WeakReference<ThreadLocal<?>> {            /** The value associated with this ThreadLocal. */            Object value;            Entry(ThreadLocal<?> k, Object v) {                super(k);                value = v;            }        }

Entry继承自WeakReference

Entry key为ThreadLocal<?>,value为ThreadLocal的T

当key为null的时候,表示key不再引用,代表实体可以从表中除去

Entry数组

        private Entry[] table;

构造器


关于ThreadLocalMap

  1. ThreadLocalMap是一个用户自定义的hash map。
  2. ThreadLocalMap适合掌管线程本地数据
  3. ThreadLocalMap没有暴露任何操作给ThreadLocal类之外的类
  4. ThreadLocalMap package内可见,为了允许Thread类的访问
  5. 为了处理大个,生命周期长的使用情况,hash表entry使用WeakReference做key
  6. 引用队列如果没有使用,entry只能保证在空间不足的时候remove掉

ThreadLocal 与 ThreadLocalMap 、Entry、Thread的关系


  1. 一个线程持有一个ThreadLocalMap引用
  2. 一个ThreadLocalMap可以持有多个Entry,ThreadLocalMap本身就持有Entry 数组的引用
  3. 一个Entry持有一个ThreadLocal的Weak Reference
  4. 间接的:一个线程可以持有多个ThreadLocal的引用
  5. 一个ThreadLocal引用可以被多个线程分别持有





0 0
原创粉丝点击