Java ThreadLocal 类

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

代码

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() {

				@Override
				public 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 = 199
TestMain-> test Thread-2 thread data = 16
TestMain-> test Thread-0 thread data = 55
A->testA() Thread-2 thread data 16
A->testA() Thread-1 thread data 199
A->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();
	}

	@Override
	public 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() {

				@Override
				public void run() {
					ThreadSingleton ts1 = ThreadSingleton.getInstance();
					ThreadSingleton ts2 = ThreadSingleton.getInstance();
					System.out.println(ts1);
					System.out.println(ts2);
				}

			}.start();
		}
	}

}

输出结果

ThreadSingleton, threadName = Thread-2 #1024915921
ThreadSingleton, threadName = Thread-2 #1024915921
ThreadSingleton, threadName = Thread-3 #2121724417
ThreadSingleton, threadName = Thread-3 #2121724417
ThreadSingleton, threadName = Thread-0 #1647036297
ThreadSingleton, threadName = Thread-0 #1647036297
ThreadSingleton, threadName = Thread-1 #113690433
ThreadSingleton, threadName = Thread-4 #185211847
ThreadSingleton, threadName = Thread-1 #113690433
ThreadSingleton, 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引用可以被多个线程分别持有





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值