0
点赞
收藏
分享

微信扫一扫

Java.ThreadLocal InheritableThreadLocal TransmittableThreadLocal 源码解析

古得曼_63b6 2022-04-25 阅读 52

前言

数据结构

线程缓存ThreadLocal

原来思路

private static final Map<Long,Object> ThreadLoacl1 = new HashMap<>();
static {
    ThreadLoacl1.put(Thread.currentThread().getId(),"value");
}

正确思路

Thread{
      ThreadLocalMap  threadLocals
}

// 自己新建的一个Map,就是一个数组,只不过存取的时候下标按照hash来算出来的
ThreadLocalMap{
       Entry[] table
}

Entry{
       ThreadLocal tl;
       Object value;
}

合并一块:
Thread{
[{ThreadLocal , Object },{ThreadLocal , Object }]
}

也就是数据是在Thread中存储着呢,而 static的ThreadLocal 才是哪个key。

Thread和ThreadLocal关系

两个在一个packge内

Thread.threadLocals 是 default,也就是包内类可见

ThreadLocal中可以给Thread对象的threadLocals属性直接赋值

Thread.inheritableThreadLocals类似threadLocals,只不过是给InheritableThreadLocal访问的

InheritableThreadLocal 是ThreadLocal子类

在new Thread()的时候,init方法 会将当前线程的inheritableThreadLocals属性中的值,赋值给子线程inheritableThreadLocals变量中

ThreadLocal

获取当前线程

Thread t = Thread.currentThread();

getMap 方法

ThreadLocal中:return  t.threadLocals

InheritableThreadLocal重写了该方法:return t.inheritableThreadLocals;

set 设置值

获取Thread中的ThreadLocals Map对象,存储数据到Map中

MyThreadLocal1.ThreadLocalMap map = getMap((MyThread1) t);
if (map != null)
    map.set(this, value);

get 获取值

获取Thread中的ThreadLocals Map对象,获取数据从Map中

// 获取线程Thread中map数据
MyThreadLocal1.ThreadLocalMap map = getMap(t);
if (map != null) {
    //  <当前ThreadLocal引用,引用>
    MyThreadLocal1.ThreadLocalMap.Entry e = map.getEntry(this);
    if (e != null) {
        @SuppressWarnings("unchecked")
        T result = (T)e.value;
        return result;
    }

createInheritedMap

复制一个继承来的Map

ThreadLocalMap

expunge 清除

Stale 腐烂

slot 槽位,map中table数组的一个元素

Entry

Entry extends WeakReference<MyThreadLocal1<?>>

Entity中比如有属性是弱引用

这个弱引用是MyThreadLocal1类型

setThreshold

设置rehash阈值,即超过2/3就rehash

rehash

expungeStaleEntries 清除腐烂实体

清除后占用 如果超过阈值 3/4就 resize

resize

数组长度翻倍,重写根据key来hash存储

HashCode

核心代码:new AtomicInteger().getAndAdd(0x61c88647)

private final int threadLocalHashCode = nextHashCode();

private static AtomicInteger nextHashCode = new AtomicInteger();

private static final int HASH_INCREMENT = 0x61c88647;

/**
 * 线程安全获取一个hashCode
 * @return
 */
private static int nextHashCode() {
    return nextHashCode.getAndAdd(HASH_INCREMENT);
}

Thread

Thread

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

Init

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize) {
    init(g, target, name, stackSize, null, true);
}

inheritThreadLocals == true

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals){

Thread parent = currentThread();

if (inheritThreadLocals && parent.inheritableThreadLocals != null)
    this.inheritableThreadLocals =         ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}

InheritableThreadLocal

按照ThreadLocal的流程:

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

map.set

map.get

map.remove

只有getMap方法获取到的Thread对象属性不同

inheritableThreadLocals 才会被复制

threadLocals是不会被复制的

InheritableThreadLocal

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

测试验证

out:

thread name:Thread-0

mythread 2 local : null

mythread 2 inlocal : 345

public class Test3 {

    public static  ThreadLocal tl = new ThreadLocal();
    public static  InheritableThreadLocal itl = new InheritableThreadLocal();

    public static void main(String[] args) {

        final Thread thread = Thread.currentThread();

        tl.set("123");
        itl.set("345");

        new MyThread2().start();

        try {
            Thread.sleep(10 * 1000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}


public class MyThread2 extends  Thread{
    public MyThread2(){
        super();
    }

    @Override
    public void run() {
        System.out.println("thread name:"+super.getName());
        try {
            Thread.sleep(1 * 1000l);
            System.out.println("mythread 2 local : " + Test3.tl.get());
            System.out.println("mythread 2 inlocal : " + Test3.itl.get());

            Thread.sleep(3 * 1000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ThreadLocal&InheritableThreadLocal&TransmittableThreadLocal

比较

ThreadLocal:

  • 一个线程内
  • 父子线程 不能传递值

InheritableThreadLocal

  • extends ThreadLocal
  • 父子线程,传递过程是new Thread
  • 线程复用,线程池场景,就会发现线程是上次的

TransmittableThreadLocal,

  • extends InheritableThreadLocal
  • 可传递,在线程池借出线程和回收线程改造,所以线程池必须用代理的,否则不生效,就是父子线程传值

示例

out:
========== 0
pool-1-thread-1 local : null
pool-1-thread-1 inlocal :  --- 0
pool-1-thread-1 transmittable :  --- 0

========== 1
pool-1-thread-2 local : null
pool-1-thread-2 inlocal :  --- 1
pool-1-thread-2 transmittable :  --- 1

========== 2
pool-1-thread-2 local : null
pool-1-thread-2 inlocal :  --- 1
pool-1-thread-2 transmittable :  --- 2

import java.util.concurrent.*;

public class ThreadPoolTester {

    private static ExecutorService pool;

    public static  ThreadLocal tl = new ThreadLocal();
    public static  InheritableThreadLocal itl = new InheritableThreadLocal();
    public static  TransmittableThreadLocal ttl = new TransmittableThreadLocal();

    public static void main(String[] args) {
        //maximumPoolSize设置为2 ,拒绝策略为AbortPolic策略,直接抛出异常
        pool = TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(1,
                2,
                1000,
                TimeUnit.MILLISECONDS,
                new SynchronousQueue<Runnable>(),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()));

        for (int i = 0; i < 3; i++) {
            tl.set(" --- " + i);
            itl.set(" --- " + i);
            ttl.set(" --- " + i);
            System.out.println("========== " + i);
            pool.execute(new ThreadTask());
            try {
                Thread.sleep(2 * 1000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class ThreadTask implements Runnable {
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName()+" local : " + ThreadPoolTester.tl.get());
                System.out.println( Thread.currentThread().getName()+" inlocal : " + ThreadPoolTester.itl.get());
                System.out.println(Thread.currentThread().getName()+" transmittable : " + ThreadPoolTester.ttl.get()+"\n");

                Thread.sleep(2 * 1000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

附录

举报

相关推荐

0 条评论