ThreadLocal类

java并发编程之美 学习笔记

示例

public class MyThreadLocalTest1 {
	static ThreadLocal<Integer> localVariable = new ThreadLocal<>();

	static final int THREAD_NUM = 5;
	static void safe(int index)  {
		new Thread(() ->{
			localVariable.set(index);
			try {
				TimeUnit.SECONDS.sleep(THREAD_NUM - index);
			} catch (InterruptedException e) {
			}
			System.out.println("thread_"+index+" 获得的值为:"+ localVariable.get());
		}).start();
	}

	static Integer variable = -1;
	static void unsafe(int index) {
		new Thread(() ->{
			variable = index;
			try {
				TimeUnit.SECONDS.sleep(THREAD_NUM - index);
			} catch (InterruptedException e) {
			}
			System.out.println("thread_"+index+" 获得的值为:"+ variable);
		}).start();
	}
}

unsafe()
测试代码:

IntStream.rangeClosed(1,THREAD_NUM).forEach(index -> {
	unsafe(index);
});

运行结果:
在这里插入图片描述
safe()
测试代码

IntStream.rangeClosed(1,THREAD_NUM).forEach(index -> {
		safe(index);
	});

运行结果:
在这里插入图片描述

源码分析

ThreadLocal类

初始化

public class ThreadLocal<T> {
    public ThreadLocal() {
    }
}

get()

public class ThreadLocal<T> {
    public T get() {
        Thread t = Thread.currentThread();
        //1.
        ThreadLocalMap map = getMap(t);
        if (map != null) {
        	//获取Entry, key为this即ThreadLocal实例对象;
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                T result = (T)e.value;
                return result;
            }
        }
        //2.
        return setInitialValue();
    }

    //1.获取当前现成的 ThreadLocalMap threadLocals属性
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    //2.若map为空,则初始化一个ThreadLocalMap并初始化到Thread的threadLocals属性中
    private T setInitialValue() {
    	//3.
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
        	//4.
            createMap(t, value);
        return value;
    }

    //3.初始值默认为null,可由子类覆盖重写
    protected T initialValue() {
        return null;
    }
	
	//4.创建一个ThreadLocalMap,并给初始值
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

set()

public void set(T value) {
      Thread t = Thread.currentThread();
      ThreadLocalMap map = getMap(t);
      if (map != null)
      	  //向map中设置值,key为当前ThreadLocal 实例对象;
          map.set(this, value);
      else	
      	  //若map为空,则创建一个,在get()中已经分析过,这里不再赘述
          createMap(t, value);
  }

ThreadLocalMap类

ThreadLocalMapThreadLocal的静态内部类.

static class ThreadLocalMap {
	static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }

    private static final int INITIAL_CAPACITY = 16;
    private int size = 0;
	private Entry[] table;

    ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
        table = new Entry[INITIAL_CAPACITY];
        //计算当前ThreadLocal的hash值 在“桶”中的位置.
        int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
        //新增一个Entry
        table[i] = new Entry(firstKey, firstValue);
        size = 1;
        setThreshold(INITIAL_CAPACITY);
    }

    private Entry getEntry(ThreadLocal<?> key) {
        int i = key.threadLocalHashCode & (table.length - 1);
        Entry e = table[i];
        if (e != null && e.get() == key)
        	//当找到正确的entry时,直接返回
            return e;
        else
        	//未正确找到时,做特殊操作(略....)
            return getEntryAfterMiss(key, i, e);
    }

    private void set(ThreadLocal<?> key, Object value) {
        Entry[] tab = table;
        int len = tab.length;
        //计算当前key的hash值 在“桶”中的位置.
        int i = key.threadLocalHashCode & (len-1);

        for (Entry e = tab[i];
             e != null;
             e = tab[i = nextIndex(i, len)]) {
            ThreadLocal<?> k = e.get();

            if (k == key) {
            	//当“桶” i位置存在k,且与key相同时,直接更新值
                e.value = value;
                return;
            }

            if (k == null) {
            	//当“桶” i位置存在k,但k为空时,替换当前之前的entry
                replaceStaleEntry(key, value, i);
                return;
            }
        }

        //当key不存在时,直接新增entry
        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
    }

}

补充:ThreadLocal.threadLocalHashCode逻辑

//threadLocalHashCode 为实例变量
private final int threadLocalHashCode = nextHashCode();

private static int nextHashCode() {
  	//nextHashCode为静态变量,所以所有的ThreadLocal实例共享一份;
    return nextHashCode.getAndAdd(HASH_INCREMENT);
}

private static AtomicInteger nextHashCode = new AtomicInteger();
private static final int HASH_INCREMENT = 0x61c88647;

此段代码可以理解为:每new一个ThreadLocal()对象,都需要将nextHashCode自增HASH_INCREMENT值作为该对象的hashCode.

Thread类

public class Thread implements Runnable {
	//每个线程对象都有threadLocals ,和 inheritableThreadLocals 成员属性;
   ThreadLocal.ThreadLocalMap threadLocals = null;
   ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}

尝试总结

每个Thread中都有可能会定义多个ThreadLocal属性,这些属性全部都被定义在一个叫做ThreadLocalMap属性中,它的结构可以看成为Map<ThreadLocal,Object>,当我们需要get()获取值时,会使用ThreadLocal实例对象作为key,去map中寻找对应的值并返回。

在这里插入图片描述

ThreadLocal使用

ThreadLocal不支持继承性

public void test() {
	ThreadLocal threadLocal = new ThreadLocal();
	threadLocal.set("threadLocal");
	new Thread(() -> {
		System.out.println("SUB---threadLocal----" + threadLocal.get());
	}).start();
	System.out.println("MAIN---threadLocal----" + threadLocal.get());
}

打印结果
sub线程打印结果为null;

InheritableThreadLocal

InheritableThreadLocal可继承

	public void test2() {
		//InheritableThreadLocal 可继承
		InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
		inheritableThreadLocal.set("inheritableThreadLocal");

		new Thread(() -> {
			System.out.println("SUB----inheritableThreadLocal----" + inheritableThreadLocal.get());
		}).start();

		System.out.println("MAIN---inheritableThreadLocal----" + inheritableThreadLocal.get());
	}

执行结果:
在这里插入图片描述

InheritableThreadLocal类

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
    protected T childValue(T parentValue) {
        return parentValue;
    }

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

    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

InheritableThreadLocal类相对简单,重写了getMap()和createMap方法,与ThreadLocal的区别是,它使用的是Thread.inheritableThreadLocals属性作为map的“载体”。
那它是如何实现可继承性的呢,答案就在Thread类中。

public class Thread implements Runnable {
    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
 		
    	//当前线程为 parent线程;
        Thread parent = currentThread();
        //略....

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);

        //如果父线程 inheritableThreadLocals 不为空,即父线程定义了 InheritableThreadLocal变量;
        if (parent.inheritableThreadLocals != null)
        	//当前Thread的inheritableThreadLocals,则继承线程的属性
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
       
       
        this.stackSize = stackSize;
        tid = nextThreadID();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值