ThreadLocal 【JDK1.8】

ThreadLocal 【JDK1.8】
public class TestThreadLocal extends Thread{

//1.在线程的run方法外 new ThreadLocal对象
    ThreadLocal<ThreadLocal> threadLocal = new ThreadLocal();

    @Override
    public void run(){

        if ("Thread-1".equals(Thread.currentThread().getName()))
        {
            //如果是线程1,就等待100ms完成,再执行.保证先执行0,再执行1
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
       System.out.println(Thread.currentThread().getName()+"  前  "+threadLocal.get());
        threadLocal.set(threadLocal);
        System.out.println(Thread.currentThread().getName()+"  后  "+threadLocal.get());

    }


    public static void main(String[] args) {
        TestThreadLocal t1 = new TestThreadLocal();
        TestThreadLocal t2 = new TestThreadLocal();

        t1.start();
        t2.start();

        try {
            sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}

执行结果

Thread-0  前  null
Thread-0  后  java.lang.ThreadLocal@3554f93f
Thread-1  前  null
Thread-1  后  java.lang.ThreadLocal@b8bf527

简单分析:

Thread-0先执行,往ThreadLoacl里存入对象,但当Thread-1去存之前去拿时,还是空。验证了ThradLocal线程安全,隔离。


ThreadLocal的set 和 get 方法

set方法

  • threadLocal.set(threadLocal);
//ThreadLocal.set(T value)
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t); //getMap(t)方法
        if (map != null) {
            map.set(this, value);   //正常map的set方法,键为当前threadLocal对象
        } else {
            createMap(t, value);	//2.1 节  createMap
        }
    }

先获取当前线程,然后获取ThreadLocalMap对象,将值set入map中,map的**key为ThreadLocal对象,value为传入的值**。

  • getMap(t)

    ThreadLocalMap map = getMap(t);

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

返回当前线程的threadLocals对象。

// Thread类中threadLocals对象
ThreadLocal.ThreadLocalMap threadLocals = null;
  • createMap(t, value);
//ThreadLocal.createMap(Thread t, T firstValue)
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

createMap方法即创建ThreadLocalMap对象,并存入值。

  • ThreadLocalMapThreadLocal静态内部类
//ThreadLocal里的静态内部类ThreadLocalMap
static class ThreadLocalMap {
   	/**
        * The initial capacity -- MUST be a power of two.
        */
       private static final int INITIAL_CAPACITY = 16;

       /**
        * The table, resized as necessary.
        * table.length MUST always be a power of two.
        */
       private Entry[] table;

       /**
        * The number of entries in the table.
        */
       private int size = 0;

       /**
        * The next size value at which to resize.
        */
       private int threshold; // Default to 0

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

    private void set(ThreadLocal<?> key, Object value) {...}

    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);
    }    
   
   
}

get方法

  • threadLocal.get();
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);  //2.2节 getMap
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
  • map.getEntry(this);
 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);
     }    

总结

每个Thread中都具备一个ThreadLocalMap,每个ThreadLocalMap可以存储多个【key=ThreadLocal,value=自设置】的map键值对。

调用threadlocal.set()方法,即是传入当前threadlocal对象去当前thread类中去找map【thread类中的threadlocalmap引用】,找到map后将其键值对存入map【key=threadlocal对象,value=set方法参数】。

调用threadlocal.get()方法,即是传入当前threadlocal对象去当前thread类中去找map拿值。该map中可以还储存其他key=threadlocal2 的键值对。

ThreadLocal本身并不存储值,它只是在线程的ThreadLocalMap变量中作为一个key来让线程从ThreadLocalMap获取value,每个value都是与ThreadLocal对象关联在一起的。





中途发现了一个好玩的事情,关于join()方法

t.join() 的作用是 谁执行t.join()方法就等待t执行完毕(t是一个线程实体)

如果是 Thread.currentThread().join(); 呢?

结果是:线程一直在阻塞,无法终止。自己等待自己结束,这也是个坑呀。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值